Edit

kc3-lang/angle/tests/angle_tests/BlitFramebufferANGLETest.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2014-07-17 10:40:49
    Hash : b759a748
    Message : Fix test class names to reflect their class-ness. Style guide dictates a camel case scheme for classes. Since the tests are actually classes, update their names to reflect that. Change-Id: Ib7422b6d8c5de8414765439704fc103eae8b2d63 Reviewed-on: https://chromium-review.googlesource.com/208680 Tested-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org>

  • tests/angle_tests/BlitFramebufferANGLETest.cpp
  • #include "ANGLETest.h"
    
    class BlitFramebufferANGLETest : public ANGLETest
    {
    protected:
        BlitFramebufferANGLETest()
        {
            setWindowWidth(256);
            setWindowHeight(256);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
            setConfigDepthBits(24);
    
            mCheckerProgram = 0;
            mBlueProgram = 0;
    
            mOriginalFBO = 0;
    
            mUserFBO = 0;
            mUserColorBuffer = 0;
            mUserDepthStencilBuffer = 0;
    
            mSmallFBO = 0;
            mSmallColorBuffer = 0;
            mSmallDepthStencilBuffer = 0;
    
            mColorOnlyFBO = 0;
            mColorOnlyColorBuffer = 0;
    
            mDiffFormatFBO = 0;
            mDiffFormatColorBuffer = 0;
    
            mDiffSizeFBO = 0;
            mDiffSizeColorBuffer = 0;
    
            mMRTFBO = 0;
            mMRTColorBuffer0 = 0;
            mMRTColorBuffer1 = 0;
    
            mRGBAColorbuffer = 0;
            mRGBAFBO = 0;
    
            mBGRAMultisampledRenderbuffer = 0;
            mBGRAMultisampledFBO = 0;
        }
    
        virtual void SetUp()
        {
            ANGLETest::SetUp();
    
            const std::string passthroughVS = SHADER_SOURCE
            (
                precision highp float;
                attribute vec4 position;
                varying vec4 pos;
    
                void main()
                {
                    gl_Position = position;
                    pos = position;
                }
            );
    
            const std::string checkeredFS = SHADER_SOURCE
            (
                precision highp float;
                varying vec4 pos;
    
                void main()
                {
                    if (pos.x * pos.y > 0.0)
                    {
                        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
                    }
                    else
                    {
                        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
                    }
                }
            );
    
            const std::string blueFS = SHADER_SOURCE
            (
                precision highp float;
                varying vec4 pos;
    
                void main()
                {
                    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
                }
            );
    
            mCheckerProgram = compileProgram(passthroughVS, checkeredFS);
            mBlueProgram = compileProgram(passthroughVS, blueFS);
            if (mCheckerProgram == 0 || mBlueProgram == 0)
            {
                FAIL() << "shader compilation failed.";
            }
    
            EXPECT_GL_NO_ERROR();
    
            GLint originalFBO;
            glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originalFBO);
            if (originalFBO >= 0)
            {
                mOriginalFBO = (GLuint)originalFBO;
            }
    
            GLenum format = GL_BGRA8_EXT;
            
            glGenFramebuffers(1, &mUserFBO);
            glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
            glGenTextures(1, &mUserColorBuffer);
            glGenRenderbuffers(1, &mUserDepthStencilBuffer);
            glBindTexture(GL_TEXTURE_2D, mUserColorBuffer);
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, getWindowWidth(), getWindowHeight());
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mUserColorBuffer, 0);
            glBindRenderbuffer(GL_RENDERBUFFER, mUserDepthStencilBuffer);
            glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, getWindowWidth(), getWindowHeight());
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mUserDepthStencilBuffer);
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mUserDepthStencilBuffer);
    
            ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
            ASSERT_GL_NO_ERROR();
    
            glGenFramebuffers(1, &mSmallFBO);
            glBindFramebuffer(GL_FRAMEBUFFER, mSmallFBO);
            glGenTextures(1, &mSmallColorBuffer);
            glGenRenderbuffers(1, &mSmallDepthStencilBuffer);
            glBindTexture(GL_TEXTURE_2D, mSmallColorBuffer);
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, getWindowWidth() / 2, getWindowHeight() / 2);
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mSmallColorBuffer, 0);
            glBindRenderbuffer(GL_RENDERBUFFER, mSmallDepthStencilBuffer);
            glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, getWindowWidth() / 2, getWindowHeight() / 2);
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mSmallDepthStencilBuffer);
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mSmallDepthStencilBuffer);
    
            ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
            ASSERT_GL_NO_ERROR();
    
            glGenFramebuffers(1, &mColorOnlyFBO);
            glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
            glGenTextures(1, &mColorOnlyColorBuffer);
            glBindTexture(GL_TEXTURE_2D, mColorOnlyColorBuffer);
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, getWindowWidth(), getWindowHeight());
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorOnlyColorBuffer, 0);
    
            ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
            ASSERT_GL_NO_ERROR();
    
            glGenFramebuffers(1, &mDiffFormatFBO);
            glBindFramebuffer(GL_FRAMEBUFFER, mDiffFormatFBO);
            glGenTextures(1, &mDiffFormatColorBuffer);
            glBindTexture(GL_TEXTURE_2D, mDiffFormatColorBuffer);
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB565, getWindowWidth(), getWindowHeight());
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDiffFormatColorBuffer, 0);
    
            ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
            ASSERT_GL_NO_ERROR();
    
            glGenFramebuffers(1, &mDiffSizeFBO);
            glBindFramebuffer(GL_FRAMEBUFFER, mDiffSizeFBO);
            glGenTextures(1, &mDiffSizeColorBuffer);
            glBindTexture(GL_TEXTURE_2D, mDiffSizeColorBuffer);
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, getWindowWidth()*2, getWindowHeight()*2);
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mDiffSizeColorBuffer, 0);
    
            ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
            ASSERT_GL_NO_ERROR();
    
            if (extensionEnabled("GL_EXT_draw_buffers"))
            {
                glGenFramebuffers(1, &mMRTFBO);
                glBindFramebuffer(GL_FRAMEBUFFER, mMRTFBO);
                glGenTextures(1, &mMRTColorBuffer0);
                glGenTextures(1, &mMRTColorBuffer1);
                glBindTexture(GL_TEXTURE_2D, mMRTColorBuffer0);
                glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, getWindowWidth(), getWindowHeight());
                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mMRTColorBuffer0, 0);
                glBindTexture(GL_TEXTURE_2D, mMRTColorBuffer1);
                glTexStorage2DEXT(GL_TEXTURE_2D, 1, format, getWindowWidth(), getWindowHeight());
                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mMRTColorBuffer1, 0);
    
                ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
                ASSERT_GL_NO_ERROR();
            }
    
            if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
            {
                // Test blit between RGBA and multisampled BGRA
                glGenTextures(1, &mRGBAColorbuffer);
                glBindTexture(GL_TEXTURE_2D, mRGBAColorbuffer);
                glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, getWindowWidth(), getWindowHeight());
    
                glGenFramebuffers(1, &mRGBAFBO);
                glBindFramebuffer(GL_FRAMEBUFFER, mRGBAFBO);
                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mRGBAColorbuffer, 0);
    
                ASSERT_GL_NO_ERROR();
                ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
    
                glGenRenderbuffers(1, &mBGRAMultisampledRenderbuffer);
                glBindRenderbuffer(GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer);
                glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_BGRA8_EXT, getWindowWidth(), getWindowHeight());
    
                glGenFramebuffers(1, &mBGRAMultisampledFBO);
                glBindFramebuffer(GL_FRAMEBUFFER, mBGRAMultisampledFBO);
                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer);
    
                ASSERT_GL_NO_ERROR();
                ASSERT_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
            }
    
            glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
        }
    
        virtual void TearDown()
        {
            glDeleteProgram(mCheckerProgram);
            glDeleteProgram(mBlueProgram);
    
            glDeleteFramebuffers(1, &mUserFBO);
            glDeleteTextures(1, &mUserColorBuffer);
            glDeleteRenderbuffers(1, &mUserDepthStencilBuffer);
    
            glDeleteFramebuffers(1, &mSmallFBO);
            glDeleteTextures(1, &mSmallColorBuffer);
            glDeleteRenderbuffers(1, &mSmallDepthStencilBuffer);
    
            glDeleteFramebuffers(1, &mColorOnlyFBO);
            glDeleteTextures(1, &mSmallDepthStencilBuffer);
    
            glDeleteFramebuffers(1, &mDiffFormatFBO);
            glDeleteTextures(1, &mDiffFormatColorBuffer);
    
            glDeleteFramebuffers(1, &mDiffSizeFBO);
            glDeleteTextures(1, &mDiffSizeColorBuffer);
    
            if (extensionEnabled("GL_EXT_draw_buffers"))
            {
                glDeleteFramebuffers(1, &mMRTFBO);
                glDeleteTextures(1, &mMRTColorBuffer0);
                glDeleteTextures(1, &mMRTColorBuffer1);
            }
    
            if (mRGBAColorbuffer != 0)
            {
                glDeleteTextures(1, &mRGBAColorbuffer);
            }
    
            if (mRGBAFBO != 0)
            {
                glDeleteFramebuffers(1, &mBGRAMultisampledFBO);
            }
    
            if (mBGRAMultisampledRenderbuffer != 0)
            {
                glDeleteRenderbuffers(1, &mBGRAMultisampledRenderbuffer);
            }
    
            if (mBGRAMultisampledFBO != 0)
            {
                glDeleteFramebuffers(1, &mBGRAMultisampledFBO);
            }
    
            ANGLETest::TearDown();
        }
    
        GLuint mCheckerProgram;
        GLuint mBlueProgram;
    
        GLuint mOriginalFBO;
    
        GLuint mUserFBO;
        GLuint mUserColorBuffer;
        GLuint mUserDepthStencilBuffer;
    
        GLuint mSmallFBO;
        GLuint mSmallColorBuffer;
        GLuint mSmallDepthStencilBuffer;
    
        GLuint mColorOnlyFBO;
        GLuint mColorOnlyColorBuffer;
    
        GLuint mDiffFormatFBO;
        GLuint mDiffFormatColorBuffer;
    
        GLuint mDiffSizeFBO;
        GLuint mDiffSizeColorBuffer;
    
        GLuint mMRTFBO;
        GLuint mMRTColorBuffer0;
        GLuint mMRTColorBuffer1;
    
        GLuint mRGBAColorbuffer;
        GLuint mRGBAFBO;
    
        GLuint mBGRAMultisampledRenderbuffer;
        GLuint mBGRAMultisampledFBO;
    };
    
    // Draw to user-created framebuffer, blit whole-buffer color to original framebuffer.
    TEST_F(BlitFramebufferANGLETest, BlitColorToDefault)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.8f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    }
    
    // Draw to system framebuffer, blit whole-buffer color to user-created framebuffer.
    TEST_F(BlitFramebufferANGLETest, ReverseColorBlit)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.8f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    }
    
    // blit from user-created FBO to system framebuffer, with the scissor test enabled.
    TEST_F(BlitFramebufferANGLETest, ScissoredBlit)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.8f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glScissor(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
        glEnable(GL_SCISSOR_TEST);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glDisable(GL_SCISSOR_TEST);
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
    }
    
    // blit from system FBO to user-created framebuffer, with the scissor test enabled.
    TEST_F(BlitFramebufferANGLETest, ReverseScissoredBlit)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.8f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        glScissor(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
        glEnable(GL_SCISSOR_TEST);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glDisable(GL_SCISSOR_TEST);
    
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
        
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
    }
    
    // blit from user-created FBO to system framebuffer, using region larger than buffer.
    TEST_F(BlitFramebufferANGLETest, OversizedBlit)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.8f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    }
    
    // blit from system FBO to user-created framebuffer, using region larger than buffer.
    TEST_F(BlitFramebufferANGLETest, ReverseOversizedBlit)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.8f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 0, 0, getWindowWidth() * 2, getWindowHeight() * 2, 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    }
    
    // blit from user-created FBO to system framebuffer, with depth buffer.
    TEST_F(BlitFramebufferANGLETest, BlitWithDepth)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glDepthMask(GL_TRUE);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glEnable(GL_DEPTH_TEST);
    
        drawQuad(mCheckerProgram, "position", 0.3f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
        drawQuad(mBlueProgram, "position", 0.8f);
    
        glDisable(GL_DEPTH_TEST);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    }
    
    // blit from system FBO to user-created framebuffer, with depth buffer.
    TEST_F(BlitFramebufferANGLETest, ReverseBlitWithDepth)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glEnable(GL_DEPTH_TEST);
    
        drawQuad(mCheckerProgram, "position", 0.3f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
    
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        // if blit is happening correctly, this quad will not draw, because it is behind the blitted one
    
        drawQuad(mBlueProgram, "position", 0.8f);
    
        glDisable(GL_DEPTH_TEST);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    }
    
    // blit from one region of the system fbo to another-- this should fail.
    TEST_F(BlitFramebufferANGLETest, BlitSameBufferOriginal)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.3f);
    
        EXPECT_GL_NO_ERROR();
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight(), getWindowWidth() / 2, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    // blit from one region of the system fbo to another.
    TEST_F(BlitFramebufferANGLETest, BlitSameBufferUser)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.3f);
    
        EXPECT_GL_NO_ERROR();
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight(), getWindowWidth() / 2, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    TEST_F(BlitFramebufferANGLETest, BlitPartialColor)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, 0, getWindowHeight() / 2, getWindowWidth() / 2, getWindowHeight(),
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4, 255, 255, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
    }
    
    TEST_F(BlitFramebufferANGLETest, BlitDifferentSizes)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mSmallFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mSmallFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
    
        EXPECT_GL_NO_ERROR();
    }
    
    TEST_F(BlitFramebufferANGLETest, BlitWithMissingAttachments)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
    
        glClear(GL_COLOR_BUFFER_BIT);
        drawQuad(mCheckerProgram, "position", 0.3f);
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mColorOnlyFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        // depth blit request should be silently ignored, because the read FBO has no depth attachment
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                               GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); 
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    
        // unlike in the depth blit tests, this *should* draw a blue quad, because depth info
        // has not been copied
        glEnable(GL_DEPTH_TEST);
        drawQuad(mBlueProgram, "position", 0.8f);
        glDisable(GL_DEPTH_TEST);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0,   0, 255, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0,   0, 255, 255);
    }
    
    TEST_F(BlitFramebufferANGLETest, BlitStencil)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT);
        // fill the stencil buffer with 0x1
        glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
        glEnable(GL_STENCIL_TEST); 
        drawQuad(mCheckerProgram, "position", 0.3f);
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glClearStencil(0x0);
        glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        // depth blit request should be silently ignored, because the read FBO has no depth attachment
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                               GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); 
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    
        glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
        drawQuad(mBlueProgram, "position", 0.8f); // blue quad will draw if stencil buffer was copied
        glDisable(GL_STENCIL_TEST);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0,   0, 255, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0,   0, 255, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0,   0, 255, 255);
    }
    
    // make sure that attempting to blit a partial depth buffer issues an error
    TEST_F(BlitFramebufferANGLETest, BlitPartialDepthStencil)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 
                               getWindowWidth() / 2, getWindowHeight() / 2, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    // Test blit with MRT framebuffers
    TEST_F(BlitFramebufferANGLETest, BlitMRT)
    {
        if (!extensionEnabled("GL_EXT_draw_buffers"))
        {
            return;
        }
    
        GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
    
        glBindFramebuffer(GL_FRAMEBUFFER, mMRTFBO);
        glDrawBuffersEXT(2, drawBuffers);
    
        glBindFramebuffer(GL_FRAMEBUFFER, mColorOnlyFBO);
    
        glClear(GL_COLOR_BUFFER_BIT);
        
        drawQuad(mCheckerProgram, "position", 0.8f);
        
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mColorOnlyFBO);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mMRTFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
        
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_FRAMEBUFFER, mMRTFBO);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mMRTColorBuffer0, 0);
    
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4,     getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4,     getWindowHeight() / 4,   0, 255,   0, 255);
        EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255,   0,   0, 255);
        EXPECT_PIXEL_EQ(    getWindowWidth() / 4, 3 * getWindowHeight() / 4,   0, 255,   0, 255);
    
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mMRTColorBuffer0, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mMRTColorBuffer1, 0);
    }
    
    // Make sure that attempts to stretch in a blit call issue an error
    TEST_F(BlitFramebufferANGLETest, ErrorStretching)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 
                               getWindowWidth(), getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    // Make sure that attempts to flip in a blit call issue an error
    TEST_F(BlitFramebufferANGLETest, ErrorFlipping)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, getWindowWidth() / 2, getWindowHeight() / 2, 
                               0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    }
    
    TEST_F(BlitFramebufferANGLETest, Errors)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        drawQuad(mCheckerProgram, "position", 0.5f);
    
        EXPECT_GL_NO_ERROR();
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
        glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), 
                               GL_COLOR_BUFFER_BIT, GL_LINEAR);
        EXPECT_GL_ERROR(GL_INVALID_ENUM);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                               GL_COLOR_BUFFER_BIT | 234, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_VALUE);
    
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mDiffFormatFBO);
    
        glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
    
        if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
        {
            glBindFramebuffer(GL_READ_FRAMEBUFFER, mBGRAMultisampledFBO);
            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRGBAFBO);
            EXPECT_GL_NO_ERROR();
    
            glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
                                   GL_COLOR_BUFFER_BIT, GL_NEAREST);
            EXPECT_GL_ERROR(GL_INVALID_OPERATION);
        }
    
    }