Clean up MipmapTest

This refactoring is done to prepare for adding more mipmap tests for
ES3 where base level / max level is changed from 0.

1. Reuse drawQuad() from ANGLETest instead of having completely custom
quad drawing code, and reuse the same clear+draw function for both 2D
and cube map texture tests.

2. Add a helper function for clearing texture level 0 with glClear.

3. Remove a few redundant texture binding and useProgram calls.

4. Rely on sampler uniforms being set to 0 by default and texture unit
0 being active by default.

5. Remove "Offscreen" from variable names.

6. Split SetUp functions to helper functions.

7. Reuse FillWithRGBA from TextureTest also in MipmapTest.

BUG=angleproject:596
TEST=angle_end2end_tests

Change-Id: I9fd738f4b8b0a19c7aa1d267f7dbaa40a6935631
Reviewed-on: https://chromium-review.googlesource.com/338791
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
index 14fdc04..94bc018 100644
--- a/src/tests/gl_tests/MipmapTest.cpp
+++ b/src/tests/gl_tests/MipmapTest.cpp
@@ -12,6 +12,15 @@
 {
   protected:
     MipmapTest()
+        : m2DProgram(0),
+          mCubeProgram(0),
+          mTexture2D(0),
+          mTextureCube(0),
+          mLevelZeroBlueInitData(nullptr),
+          mLevelZeroWhiteInitData(nullptr),
+          mLevelOneInitData(nullptr),
+          mLevelTwoInitData(nullptr),
+          mOffscreenFramebuffer(0)
     {
         setWindowWidth(128);
         setWindowHeight(128);
@@ -21,21 +30,18 @@
         setConfigAlphaBits(8);
     }
 
-    virtual void SetUp()
+    void setUp2DProgram()
     {
-        ANGLETest::SetUp();
-
         // Vertex Shader source
         const std::string vs = SHADER_SOURCE
         (
             attribute vec4 aPosition;
-            attribute vec2 aTexCoord;
             varying vec2 vTexCoord;
 
             void main()
             {
                 gl_Position = aPosition;
-                vTexCoord = aTexCoord;
+                vTexCoord   = (aPosition.xy * 0.5) + 0.5;
             }
         );
 
@@ -54,11 +60,11 @@
         );
 
         m2DProgram = CompileProgram(vs, fs);
-        if (m2DProgram == 0)
-        {
-            FAIL() << "shader compilation failed.";
-        }
+        ASSERT_NE(0u, m2DProgram);
+    }
 
+    void setUpCubeProgram()
+    {
         // A simple vertex shader for the texture cube
         const std::string cubeVS = SHADER_SOURCE
         (
@@ -85,17 +91,16 @@
         );
 
         mCubeProgram = CompileProgram(cubeVS, cubeFS);
-        if (mCubeProgram == 0)
-        {
-            FAIL() << "shader compilation failed.";
-        }
+        ASSERT_NE(0u, mCubeProgram);
+    }
 
-        m2DTextureUniformPosition = glGetUniformLocation(m2DProgram, "uTexture");
-        m2DPositionAttributePosition = glGetAttribLocation(m2DProgram, "aPosition");
-        m2DTexCoordAttributePosition = glGetAttribLocation(m2DProgram, "aTexCoord");
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
 
-        mCubeTextureUniformPosition = glGetUniformLocation(mCubeProgram, "uTexture");
-        mCubePositionAttributePosition = glGetAttribLocation(mCubeProgram, "aPosition");
+        setUp2DProgram();
+
+        setUpCubeProgram();
 
         mLevelZeroBlueInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 0, 0, 255); // Blue
         mLevelZeroWhiteInitData = createRGBInitData(getWindowWidth(), getWindowHeight(), 255, 255, 255); // White
@@ -103,22 +108,17 @@
         mLevelTwoInitData = createRGBInitData((getWindowWidth() / 4), (getWindowHeight() / 4), 255, 0, 0);   // Red
 
         glGenFramebuffers(1, &mOffscreenFramebuffer);
-        glGenTextures(1, &mOffscreenTexture2D);
+        glGenTextures(1, &mTexture2D);
 
         // Initialize the texture2D to be empty, and don't use mips.
-        glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
+        glBindTexture(GL_TEXTURE_2D, mTexture2D);
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
-        // Bind the texture2D to the offscreen framebuffer's color buffer.
-        glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOffscreenTexture2D, 0);
-        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
-
         // Create a non-mipped texture cube. Set the negative-Y face to be blue.
-        glGenTextures(1, &mOffscreenTextureCube);
-        glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
+        glGenTextures(1, &mTextureCube);
+        glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
@@ -133,13 +133,13 @@
         ASSERT_GL_NO_ERROR();
     }
 
-    virtual void TearDown()
+    void TearDown() override
     {
         glDeleteProgram(m2DProgram);
         glDeleteProgram(mCubeProgram);
         glDeleteFramebuffers(1, &mOffscreenFramebuffer);
-        glDeleteTextures(1, &mOffscreenTexture2D);
-        glDeleteTextures(1, &mOffscreenTextureCube);
+        glDeleteTextures(1, &mTexture2D);
+        glDeleteTextures(1, &mTextureCube);
 
         SafeDeleteArray(mLevelZeroBlueInitData);
         SafeDeleteArray(mLevelZeroWhiteInitData);
@@ -163,69 +163,59 @@
         return data;
     }
 
-    void ClearAndDrawTexturedQuad(GLuint texture, GLsizei viewportWidth, GLsizei viewportHeight)
+    void clearAndDrawQuad(GLuint program, GLsizei viewportWidth, GLsizei viewportHeight)
     {
-        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
         glClear(GL_COLOR_BUFFER_BIT);
-
         glViewport(0, 0, viewportWidth, viewportHeight);
-
         ASSERT_GL_NO_ERROR();
 
-        GLfloat vertexLocations[] =
-        {
-            -1.0f,  1.0f, 0.0f,
-            -1.0f, -1.0f, 0.0f,
-             1.0f,  1.0f, 0.0f,
-             1.0f, -1.0f, 0.0f,
-        };
+        drawQuad(program, "aPosition", 0.0f);
+    }
 
-        GLfloat vertexTexCoords[] =
-        {
-            0.0f, 1.0f,
-            0.0f, 0.0f,
-            1.0f, 1.0f,
-            1.0f, 0.0f,
-        };
-
-        glUseProgram(m2DProgram);
-
-        glActiveTexture(GL_TEXTURE0);
-        glBindTexture(GL_TEXTURE_2D, texture);
-        glUniform1i(m2DTextureUniformPosition, 0);
-
-        glVertexAttribPointer(m2DPositionAttributePosition, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
-        glEnableVertexAttribArray(m2DPositionAttributePosition);
-
-        glVertexAttribPointer(m2DTexCoordAttributePosition, 2, GL_FLOAT, GL_FALSE, 0, vertexTexCoords);
-        glEnableVertexAttribArray(m2DTexCoordAttributePosition);
-
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    void clearTextureLevel0(GLenum textarget,
+                            GLuint texture,
+                            GLfloat red,
+                            GLfloat green,
+                            GLfloat blue,
+                            GLfloat alpha)
+    {
+        glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textarget, texture, 0);
+        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+        glClearColor(red, green, blue, alpha);
+        glClear(GL_COLOR_BUFFER_BIT);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
     }
 
     GLuint m2DProgram;
     GLuint mCubeProgram;
-    GLuint mOffscreenFramebuffer;
-    GLuint mOffscreenTexture2D;
-    GLuint mOffscreenTextureCube;
-
-    GLint m2DTextureUniformPosition;
-    GLint m2DPositionAttributePosition;
-    GLint m2DTexCoordAttributePosition;
-
-    GLint mCubeTextureUniformPosition;
-    GLint mCubePositionAttributePosition;
+    GLuint mTexture2D;
+    GLuint mTextureCube;
 
     GLubyte* mLevelZeroBlueInitData;
     GLubyte* mLevelZeroWhiteInitData;
     GLubyte* mLevelOneInitData;
     GLubyte* mLevelTwoInitData;
+
+  private:
+    GLuint mOffscreenFramebuffer;
 };
 
 class MipmapTestES3 : public ANGLETest
 {
   protected:
     MipmapTestES3()
+        : mTextureArray(0),
+          mTexture3D(0),
+          mArrayProgram(0),
+          mTextureArrayScaleUniformLocation(-1),
+          mTextureArraySliceUniformLocation(-1),
+          m3DProgram(0),
+          mTexture3DScaleUniformLocation(-1),
+          mTexture3DSliceUniformLocation(-1),
+          mTexture3DLODUniformLocation(-1)
+
     {
         setWindowWidth(128);
         setWindowHeight(128);
@@ -235,19 +225,12 @@
         setConfigAlphaBits(8);
     }
 
-    virtual void SetUp()
+    std::string vertexShaderSource()
     {
-        ANGLETest::SetUp();
-
-        glGenTextures(1, &mTextureArray);
-        EXPECT_GL_NO_ERROR();
-
-        ASSERT_GL_NO_ERROR();
-
         // Don't put "#version ..." on its own line. See [cpp]p1:
         // "If there are sequences of preprocessing tokens within the list of arguments that
         //  would otherwise act as preprocessing directives, the behavior is undefined"
-        const std::string vertexShaderSource = SHADER_SOURCE
+        return SHADER_SOURCE
         (   #version 300 es\n
             precision highp float;
             in vec4 position;
@@ -261,7 +244,10 @@
                 texcoord = (position.xy * 0.5) + 0.5;
             }
         );
+    }
 
+    void setUpArrayProgram()
+    {
         const std::string fragmentShaderSourceArray = SHADER_SOURCE
         (   #version 300 es\n
             precision highp float;
@@ -276,15 +262,12 @@
             }
         );
 
-        mArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceArray);
+        mArrayProgram = CompileProgram(vertexShaderSource(), fragmentShaderSourceArray);
         if (mArrayProgram == 0)
         {
             FAIL() << "shader compilation failed.";
         }
 
-        mTextureArrayUniformLocation = glGetUniformLocation(mArrayProgram, "tex");
-        ASSERT_NE(-1, mTextureArrayUniformLocation);
-
         mTextureArrayScaleUniformLocation = glGetUniformLocation(mArrayProgram, "textureScale");
         ASSERT_NE(-1, mTextureArrayScaleUniformLocation);
 
@@ -295,11 +278,10 @@
         glUniform2f(mTextureArrayScaleUniformLocation, 1.0f, 1.0f);
         glUseProgram(0);
         ASSERT_GL_NO_ERROR();
+    }
 
-        glGenTextures(1, &mTexture3D);
-
-        ASSERT_GL_NO_ERROR();
-
+    void setUp3DProgram()
+    {
         const std::string fragmentShaderSource3D = SHADER_SOURCE
         (   #version 300 es\n
             precision highp float;
@@ -315,15 +297,12 @@
             }
         );
 
-        m3DProgram = CompileProgram(vertexShaderSource, fragmentShaderSource3D);
+        m3DProgram = CompileProgram(vertexShaderSource(), fragmentShaderSource3D);
         if (m3DProgram == 0)
         {
             FAIL() << "shader compilation failed.";
         }
 
-        mTexture3DUniformLocation = glGetUniformLocation(m3DProgram, "tex");
-        ASSERT_NE(-1, mTexture3DUniformLocation);
-
         mTexture3DScaleUniformLocation = glGetUniformLocation(m3DProgram, "textureScale");
         ASSERT_NE(-1, mTexture3DScaleUniformLocation);
 
@@ -340,7 +319,19 @@
         ASSERT_GL_NO_ERROR();
     }
 
-    virtual void TearDown()
+    void SetUp() override
+    {
+        ANGLETest::SetUp();
+
+        glGenTextures(1, &mTextureArray);
+        glGenTextures(1, &mTexture3D);
+        ASSERT_GL_NO_ERROR();
+
+        setUpArrayProgram();
+        setUp3DProgram();
+    }
+
+    void TearDown() override
     {
         glDeleteTextures(1, &mTextureArray);
         glDeleteProgram(mArrayProgram);
@@ -355,12 +346,10 @@
     GLuint mTexture3D;
 
     GLuint mArrayProgram;
-    GLint mTextureArrayUniformLocation;
     GLint mTextureArrayScaleUniformLocation;
     GLint mTextureArraySliceUniformLocation;
 
     GLuint m3DProgram;
-    GLint mTexture3DUniformLocation;
     GLint mTexture3DScaleUniformLocation;
     GLint mTexture3DSliceUniformLocation;
     GLint mTexture3DLODUniformLocation;
@@ -372,7 +361,7 @@
 TEST_P(MipmapTest, DISABLED_ThreeLevelsInitData)
 {
     // Pass in level zero init data.
-    glBindTexture(GL_TEXTURE_2D, mOffscreenTexture2D);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
     ASSERT_GL_NO_ERROR();
 
@@ -380,15 +369,15 @@
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
     // Draw a full-sized quad, and check it's blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Draw a half-sized quad, and check it's blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
 
     // Draw a quarter-sized quad, and check it's blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 
     // Complete the texture by initializing the remaining levels.
@@ -405,22 +394,22 @@
     ASSERT_GL_NO_ERROR();
 
     // Draw a full-sized quad, and check it's blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Draw a half-sized quad, and check it's blue. We've not enabled mipmaps yet, so our init data for level one shouldn't be used.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
 
     // Enable mipmaps.
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
 
     // Draw a half-sized quad, and check it's green.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
 
     // Draw a quarter-sized quad, and check it's black, since we've not passed any init data for level two.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 0, 255);
 
     // Pass in level two init data.
@@ -428,45 +417,45 @@
     ASSERT_GL_NO_ERROR();
 
     // Draw a full-sized quad, and check it's blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Draw a half-sized quad, and check it's green.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
 
     // Draw a quarter-sized quad, and check it's red.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
 
     // Now disable mipmaps again, and render multiple sized quads. They should all be blue, since level 0 is blue.
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 
     // Now reset level 0 to white, keeping mipmaps disabled. Then, render various sized quads. They should be white.
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroWhiteInitData);
     ASSERT_GL_NO_ERROR();
 
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 255, 255, 255);
 
     // Then enable mipmaps again. The quads should be white, green, red respectively.
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
 
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 255, 0, 0, 255);
 }
 
@@ -478,6 +467,7 @@
 TEST_P(MipmapTest, GenerateMipmapFromInitDataThenRender)
 {
     // Pass in initial data so the texture is blue.
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, mLevelZeroBlueInitData);
 
     // Then generate the mips.
@@ -488,42 +478,40 @@
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
 
     // Now draw the texture to various different sized areas.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Use mip level 1
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
 
     // Use mip level 2
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 
     ASSERT_GL_NO_ERROR();
 
     // Disable mips. Render a quad using the texture and ensure it's blue.
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
-    // Clear level 0 of the texture.
-    glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
-    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
+    // Clear level 0 of the texture to red.
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 1.0f, 0.0f, 0.0f, 1.0f);
 
     // Reenable mips, and try rendering different-sized quads.
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
 
     // Level 0 is now red, so this should render red.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
 
     // Use mip level 1, blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
 
     // Use mip level 2, blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 }
 
@@ -532,12 +520,9 @@
 // The test ensures that the zero-level texture is correctly copied into the mipped texture before the mipmaps are generated.
 TEST_P(MipmapTest, GenerateMipmapFromRenderedImage)
 {
-    // Bind the offscreen framebuffer/texture.
-    glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
-
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
     // Clear the texture to blue.
-    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 0.0f, 0.0f, 1.0f, 1.0f);
 
     // Then generate the mips
     glGenerateMipmap(GL_TEXTURE_2D);
@@ -547,15 +532,15 @@
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
 
     // Now draw the texture to various different sized areas.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Use mip level 1
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 2, getWindowHeight() / 2);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 2, getWindowHeight() / 2);
     EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 0, 255, 255);
 
     // Use mip level 2
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 }
 
@@ -570,19 +555,14 @@
         return;
     }
 
-    // Bind the offscreen texture/framebuffer.
-    glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
+    glBindTexture(GL_TEXTURE_2D, mTexture2D);
 
     // Clear the texture to blue.
-    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    // From now on, default clear color is black.
-    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 0.0f, 0.0f, 1.0f, 1.0f);
 
     // Now, draw the texture to a quad that's the same size as the texture. This draws to the default framebuffer.
     // The quad should be blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Now go back to the texture, and generate mips on it.
@@ -591,7 +571,7 @@
 
     // Now try rendering the textured quad again. Note: we've not told GL to use the generated mips.
     // The quad should be blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Now tell GL to use the generated mips.
@@ -599,27 +579,22 @@
     EXPECT_GL_NO_ERROR();
 
     // Now render the textured quad again. It should be still be blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
 
     // Now render the textured quad to an area smaller than the texture (i.e. to force minification). This should be blue.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 
     // Now clear the texture to green. This just clears the top level. The lower mips should remain blue.
-    glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
-    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    // From now on, default clear color is black.
-    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    clearTextureLevel0(GL_TEXTURE_2D, mTexture2D, 0.0f, 1.0f, 0.0f, 1.0f);
 
     // Render a textured quad equal in size to the texture. This should be green, since we just cleared level 0.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
 
     // Render a small textured quad. This forces minification, so should render blue (the color of levels 1+).
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 0, 255, 255);
 
     // Disable mipmaps again
@@ -627,11 +602,11 @@
     ASSERT_GL_NO_ERROR();
 
     // Render a textured quad equal in size to the texture. This should be green, the color of level 0 in the texture.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth(), getWindowHeight());
+    clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 255, 0, 255);
 
     // Render a small textured quad. This would force minification if mips were enabled, but they're not. Therefore, this should be green.
-    ClearAndDrawTexturedQuad(mOffscreenTexture2D, getWindowWidth() / 4, getWindowHeight() / 4);
+    clearAndDrawQuad(m2DProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(getWindowWidth() / 8, getWindowHeight() / 8, 0, 255, 0, 255);
 }
 
@@ -639,125 +614,59 @@
 // works as expected. It tests enabling/disabling mipmaps, generating mipmaps, and rendering to level zero.
 TEST_P(MipmapTest, TextureCubeGeneralLevelZero)
 {
-    GLfloat vertexLocations[] =
-    {
-        -1.0f, 1.0f, 0.0f,
-        -1.0f, -1.0f, 0.0f,
-        1.0f, 1.0f, 0.0f,
-        1.0f, -1.0f, 0.0f,
-    };
-
-    // Set up the viewport, program, attributes, sampler and texture for the cube
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glViewport(0, 0, getWindowWidth(), getWindowHeight());
-    glUseProgram(mCubeProgram);
-    glVertexAttribPointer(mCubePositionAttributePosition, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
-    glEnableVertexAttribArray(mCubePositionAttributePosition);
-    glUniform1i(mCubeTextureUniformPosition, 0);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
 
     // Draw. Since the negative-Y face's is blue, this should be blue.
-    glClear(GL_COLOR_BUFFER_BIT);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
 
     // Generate mipmaps, and render. This should be blue.
-    glClear(GL_COLOR_BUFFER_BIT);
     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
 
     // Draw using a smaller viewport (to force a lower LOD of the texture). This should still be blue.
-    glClear(GL_COLOR_BUFFER_BIT);
-    glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
 
     // Now clear the negative-Y face of the cube to red.
-    glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
-    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
-    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    // Switch back to the default framebuffer
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
+    clearTextureLevel0(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mTextureCube, 1.0f, 0.0f, 0.0f, 1.0f);
 
     // Draw using a full-size viewport. This should be red.
-    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glViewport(0, 0, getWindowWidth(), getWindowHeight());
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
 
     // Draw using a quarter-size viewport, to force a lower LOD. This should be *BLUE*, since we only cleared level zero
     // of the negative-Y face to red, and left its mipmaps blue.
-    glClear(GL_COLOR_BUFFER_BIT);
-    glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
 
     // Disable mipmaps again, and draw a to a quarter-size viewport.
     // Since this should use level zero of the texture, this should be *RED*.
-    glClear(GL_COLOR_BUFFER_BIT);
     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
+    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
 }
 
 // This test ensures that rendering to level-zero of a TextureCube works as expected.
 TEST_P(MipmapTest, TextureCubeRenderToLevelZero)
 {
-    GLfloat vertexLocations[] =
-    {
-        -1.0f,  1.0f, 0.0f,
-        -1.0f, -1.0f, 0.0f,
-         1.0f,  1.0f, 0.0f,
-         1.0f, -1.0f, 0.0f,
-    };
-
-    // Set up the viewport, program, attributes, sampler and texture for the cube
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glViewport(0, 0, getWindowWidth(), getWindowHeight());
-    glUseProgram(mCubeProgram);
-    glVertexAttribPointer(mCubePositionAttributePosition, 3, GL_FLOAT, GL_FALSE, 0, vertexLocations);
-    glEnableVertexAttribArray(mCubePositionAttributePosition);
-    glUniform1i(mCubeTextureUniformPosition, 0);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
+    glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
 
     // Draw. Since the negative-Y face's is blue, this should be blue.
-    glClear(GL_COLOR_BUFFER_BIT);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
 
     // Now clear the negative-Y face of the cube to red.
-    glBindFramebuffer(GL_FRAMEBUFFER, mOffscreenFramebuffer);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mOffscreenTextureCube, 0);
-    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
-    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    // Switch back to the default framebuffer
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glBindTexture(GL_TEXTURE_CUBE_MAP, mOffscreenTextureCube);
+    clearTextureLevel0(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, mTextureCube, 1.0f, 0.0f, 0.0f, 1.0f);
 
     // Draw using a full-size viewport. This should be red.
-    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glViewport(0, 0, getWindowWidth(), getWindowHeight());
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth(), getWindowHeight());
     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
 
     // Draw a to a quarter-size viewport. This should also be red.
-    glClear(GL_COLOR_BUFFER_BIT);
-    glViewport(0, 0, getWindowWidth() / 4, getWindowHeight() / 4);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    clearAndDrawQuad(mCubeProgram, getWindowWidth() / 4, getWindowHeight() / 4);
     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
 }
 
@@ -768,42 +677,23 @@
     int px = getWindowWidth() / 2;
     int py = getWindowHeight() / 2;
 
-    glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
 
     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
 
     // Fill the first layer with red
     std::vector<GLubyte> pixels(4 * 16 * 16);
-    for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
-    {
-        pixels[pixelId * 4 + 0] = 255;
-        pixels[pixelId * 4 + 1] = 0;
-        pixels[pixelId * 4 + 2] = 0;
-        pixels[pixelId * 4 + 3] = 255;
-    }
+    FillWithRGBA<GLubyte>(16u * 16u, 255u, 0u, 0u, 255u, pixels.data());
 
     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
 
     // Fill the second layer with green
-    for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
-    {
-        pixels[pixelId * 4 + 0] = 0;
-        pixels[pixelId * 4 + 1] = 255;
-        pixels[pixelId * 4 + 2] = 0;
-        pixels[pixelId * 4 + 3] = 255;
-    }
+    FillWithRGBA<GLubyte>(16u * 16u, 0u, 255u, 0u, 255u, pixels.data());
 
     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
 
     // Fill the third layer with blue
-    for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
-    {
-        pixels[pixelId * 4 + 0] = 0;
-        pixels[pixelId * 4 + 1] = 0;
-        pixels[pixelId * 4 + 2] = 255;
-        pixels[pixelId * 4 + 3] = 255;
-    }
+    FillWithRGBA<GLubyte>(16u * 16u, 0u, 0u, 255u, 255u, pixels.data());
 
     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
 
@@ -817,26 +707,22 @@
     EXPECT_GL_NO_ERROR();
 
     glUseProgram(mArrayProgram);
-    glUniform1i(mTextureArrayUniformLocation, 0);
 
     EXPECT_GL_NO_ERROR();
 
     // Draw the first slice
-    glUseProgram(mArrayProgram);
     glUniform1i(mTextureArraySliceUniformLocation, 0);
     drawQuad(mArrayProgram, "position", 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
 
     // Draw the second slice
-    glUseProgram(mArrayProgram);
     glUniform1i(mTextureArraySliceUniformLocation, 1);
     drawQuad(mArrayProgram, "position", 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
 
     // Draw the third slice
-    glUseProgram(mArrayProgram);
     glUniform1i(mTextureArraySliceUniformLocation, 2);
     drawQuad(mArrayProgram, "position", 0.5f);
     EXPECT_GL_NO_ERROR();
@@ -850,31 +736,18 @@
     int px = getWindowWidth() / 2;
     int py = getWindowHeight() / 2;
 
-    glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_3D, mTexture3D);
 
     glTexStorage3D(GL_TEXTURE_3D, 5, GL_RGBA8, 16, 16, 2);
 
     // Fill the first layer with red
     std::vector<GLubyte> pixels(4 * 16 * 16);
-    for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
-    {
-        pixels[pixelId * 4 + 0] = 255;
-        pixels[pixelId * 4 + 1] = 0;
-        pixels[pixelId * 4 + 2] = 0;
-        pixels[pixelId * 4 + 3] = 255;
-    }
+    FillWithRGBA<GLubyte>(16u * 16u, 255u, 0u, 0u, 255u, pixels.data());
 
     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
 
     // Fill the second layer with green
-    for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
-    {
-        pixels[pixelId * 4 + 0] = 0;
-        pixels[pixelId * 4 + 1] = 255;
-        pixels[pixelId * 4 + 2] = 0;
-        pixels[pixelId * 4 + 3] = 255;
-    }
+    FillWithRGBA<GLubyte>(16u * 16u, 0u, 255u, 0u, 255u, pixels.data());
 
     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
 
@@ -888,13 +761,11 @@
     EXPECT_GL_NO_ERROR();
 
     glUseProgram(m3DProgram);
-    glUniform1i(mTexture3DUniformLocation, 0);
 
     EXPECT_GL_NO_ERROR();
 
     // Mipmap level 0
     // Draw the first slice
-    glUseProgram(m3DProgram);
     glUniform1f(mTexture3DLODUniformLocation, 0.);
     glUniform1f(mTexture3DSliceUniformLocation, 0.25f);
     drawQuad(m3DProgram, "position", 0.5f);
@@ -902,7 +773,6 @@
     EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
 
     // Draw the second slice
-    glUseProgram(m3DProgram);
     glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
     drawQuad(m3DProgram, "position", 0.5f);
     EXPECT_GL_NO_ERROR();
@@ -910,14 +780,11 @@
 
     // Mipmap level 1
     // The second mipmap should only have one slice.
-
-    glUseProgram(m3DProgram);
     glUniform1f(mTexture3DLODUniformLocation, 1.);
     drawQuad(m3DProgram, "position", 0.5f);
     EXPECT_GL_NO_ERROR();
     EXPECT_PIXEL_NEAR(px, py, 127, 127, 0, 255, 1.0);
 
-    glUseProgram(m3DProgram);
     glUniform1f(mTexture3DSliceUniformLocation, 0.75f);
     drawQuad(m3DProgram, "position", 0.5f);
     EXPECT_GL_NO_ERROR();
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index e74519c..22dfac3 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -11,18 +11,6 @@
 namespace
 {
 
-template <typename T>
-void FillWithRGBA(size_t pixelCount, T red, T green, T blue, T alpha, T *outArray)
-{
-    for (size_t i = 0u; i < pixelCount; ++i)
-    {
-        outArray[i * 4u]      = red;
-        outArray[i * 4u + 1u] = green;
-        outArray[i * 4u + 2u] = blue;
-        outArray[i * 4u + 3u] = alpha;
-    }
-}
-
 class TexCoordDrawTest : public ANGLETest
 {
   protected:
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index 6fa5ac7..17badb4 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -66,6 +66,18 @@
 std::ostream &operator<<(std::ostream &ostream, const GLColor &color);
 GLColor ReadColor(GLint x, GLint y);
 
+template <typename T>
+void FillWithRGBA(size_t pixelCount, T red, T green, T blue, T alpha, T *outArray)
+{
+    for (size_t i = 0u; i < pixelCount; ++i)
+    {
+        outArray[i * 4u]      = red;
+        outArray[i * 4u + 1u] = green;
+        outArray[i * 4u + 2u] = blue;
+        outArray[i * 4u + 3u] = alpha;
+    }
+}
+
 }  // namespace angle
 
 #define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \