| // Copyright (C) 2018 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| #include <gtest/gtest.h> |
| |
| #include "host-common/testing/MockGraphicsAgentFactory.h" |
| #include "Standalone.h" |
| #include "GLTestUtils.h" |
| |
| #include <memory> |
| |
| namespace gfxstream { |
| namespace { |
| |
| using gl::GLESApi; |
| using gl::GLESApi_2; |
| using gl::GLESApi_3_0; |
| using gl::GLESApi_3_1; |
| using gl::GLESApi_3_2; |
| using gl::GLESApi_CM; |
| using gl::LazyLoadedEGLDispatch; |
| using gl::LazyLoadedGLESv2Dispatch; |
| |
| struct ClearColorParam { |
| const GLESApi glVersion; |
| const bool fastBlit; |
| |
| ClearColorParam(GLESApi glVersion, bool fastBlit) |
| : glVersion(glVersion), fastBlit(fastBlit) {} |
| }; |
| |
| static void PrintTo(const ClearColorParam& param, std::ostream* os) { |
| *os << "ClearColorParam("; |
| |
| switch (param.glVersion) { |
| case GLESApi_CM: *os << "GLESApi_CM"; break; |
| case GLESApi_2: *os << "GLESApi_2"; break; |
| case GLESApi_3_0: *os << "GLESApi_3_0"; break; |
| case GLESApi_3_1: *os << "GLESApi_3_1"; break; |
| case GLESApi_3_2: *os << "GLESApi_3_2"; break; |
| default: *os << "GLESApi(" << int(param.glVersion) << ")"; break; |
| } |
| |
| *os << ", " << (param.fastBlit ? "fast blit" : "slow blit") << ")"; |
| } |
| |
| class ClearColor final : public SampleApplication { |
| public: |
| ClearColor(ClearColorParam param) : SampleApplication(256, 256, 60, param.glVersion) { |
| if (!param.fastBlit) { |
| // Disable fast blit and then recreate the color buffer to apply the |
| // change. |
| mFb->disableFastBlitForTesting(); |
| |
| mFb->closeColorBuffer(mColorBuffer); |
| mColorBuffer = mFb->createColorBuffer( |
| mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE); |
| mFb->setEmulatedEglWindowSurfaceColorBuffer(mSurface, mColorBuffer); |
| } |
| } |
| |
| ~ClearColor() { |
| auto gl = LazyLoadedGLESv2Dispatch::get(); |
| if (mFbo) { |
| gl->glDeleteFramebuffers(1, &mFbo); |
| gl->glDeleteTextures(1, &mTexture); |
| } |
| } |
| |
| void setClearColor(float r, float g, float b, float a) { |
| mRed = r; |
| mGreen = g; |
| mBlue = b; |
| mAlpha = a; |
| } |
| |
| void setUseFboCombined(bool useFbo) { |
| mUseFboCombined = useFbo; |
| } |
| |
| void setUseFbo(bool useFboDraw, bool useFboRead) { |
| mUseFboDraw = useFboDraw; |
| mUseFboRead = useFboRead; |
| } |
| |
| void initialize() override { |
| auto gl = LazyLoadedGLESv2Dispatch::get(); |
| gl->glActiveTexture(GL_TEXTURE0); |
| |
| if (!mFbo) { |
| gl->glGenFramebuffers(1, &mFbo); |
| gl->glGenTextures(1, &mTexture); |
| |
| gl->glBindTexture(GL_TEXTURE_2D, mTexture); |
| gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
| mWidth, mHeight, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| gl->glBindTexture(GL_TEXTURE_2D, 0); |
| |
| gl->glBindFramebuffer(GL_FRAMEBUFFER, mFbo); |
| gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| GL_TEXTURE_2D, mTexture, 0); |
| gl->glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| } |
| } |
| |
| void draw() override { |
| auto gl = LazyLoadedGLESv2Dispatch::get(); |
| |
| gl->glBindFramebuffer(GL_FRAMEBUFFER, mUseFboCombined ? mFbo : 0); |
| |
| if (mUseFboDraw) { |
| gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFbo); |
| } |
| if (mUseFboRead) { |
| gl->glBindFramebuffer(GL_READ_FRAMEBUFFER, mFbo); |
| } |
| |
| gl->glClearColor(mRed, mGreen, mBlue, mAlpha); |
| gl->glClear(GL_COLOR_BUFFER_BIT); |
| } |
| |
| void setNonDefaultCombinedFbo() { |
| setUseFboCombined(true); |
| } |
| |
| void setNonDefaultDrawFbo() { |
| setUseFbo(true, mUseFboRead); |
| } |
| |
| void setNonDefaultReadFbo() { |
| setUseFbo(mUseFboDraw, true); |
| } |
| |
| void drawWithColor(const float drawColor[4]) { |
| setClearColor(drawColor[0], drawColor[1], drawColor[2], drawColor[3]); |
| drawOnce(); |
| } |
| |
| void verifySwappedColor(const float wantedColor[4]) { |
| TestTexture targetBuffer = |
| createTestTextureRGBA8888SingleColor( |
| mWidth, mHeight, wantedColor[0], wantedColor[1], wantedColor[2], wantedColor[3]); |
| |
| TestTexture forRead = |
| createTestTextureRGBA8888SingleColor( |
| mWidth, mHeight, 0.0f, 0.0f, 0.0f, 0.0f); |
| |
| mFb->readColorBuffer( |
| mColorBuffer, 0, 0, mWidth, mHeight, |
| GL_RGBA, GL_UNSIGNED_BYTE, forRead.data()); |
| |
| EXPECT_TRUE( |
| ImageMatches(mWidth, mHeight, 4, mWidth, targetBuffer.data(), forRead.data())); |
| } |
| |
| private: |
| bool mUseFboCombined = false; |
| bool mUseFboDraw = false; |
| bool mUseFboRead = false; |
| |
| GLuint mFbo = 0; |
| GLuint mTexture = 0; |
| |
| float mRed = 1.0f; |
| float mGreen = 1.0f; |
| float mBlue = 1.0f; |
| float mAlpha = 1.0f; |
| }; |
| |
| static constexpr float kDrawColorRed[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; |
| static constexpr float kDrawColorGreen[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; |
| |
| class CombinedFramebufferBlit : public ::testing::Test, public ::testing::WithParamInterface<ClearColorParam> { |
| protected: |
| static void SetUpTestSuite() { |
| android::emulation::injectGraphicsAgents( |
| android::emulation::MockGraphicsAgentFactory()); |
| } |
| |
| static void TearDownTestSuite() { } |
| |
| virtual void SetUp() override { |
| mApp.reset(new ClearColor(GetParam())); |
| } |
| |
| virtual void TearDown() override { |
| mApp.reset(); |
| EXPECT_EQ(EGL_SUCCESS, LazyLoadedEGLDispatch::get()->eglGetError()) |
| << "DefaultFramebufferBlitTest TearDown found an EGL error"; |
| } |
| |
| std::unique_ptr<ClearColor> mApp; |
| }; |
| |
| TEST_P(CombinedFramebufferBlit, DefaultDrawDefaultRead) { |
| // Draw to default framebuffer; color should show up |
| mApp->drawWithColor(kDrawColorRed); |
| mApp->verifySwappedColor(kDrawColorRed); |
| } |
| |
| TEST_P(CombinedFramebufferBlit, NonDefault) { |
| mApp->drawWithColor(kDrawColorRed); |
| mApp->verifySwappedColor(kDrawColorRed); |
| |
| // Color should not be affected by the draw to a non-default framebuffer. |
| mApp->setNonDefaultCombinedFbo(); |
| |
| mApp->drawWithColor(kDrawColorGreen); |
| mApp->verifySwappedColor(kDrawColorRed); |
| } |
| |
| // Test blitting both with only the fast blit path. |
| INSTANTIATE_TEST_SUITE_P(CombinedFramebufferBlitTest, |
| CombinedFramebufferBlit, |
| testing::Values( |
| ClearColorParam(GLESApi_CM, true), |
| ClearColorParam(GLESApi_2, true), |
| ClearColorParam(GLESApi_3_0, true))); |
| |
| class NonDefaultFramebufferBlit : public CombinedFramebufferBlit { }; |
| |
| TEST_P(NonDefaultFramebufferBlit, NonDefaultDrawNonDefaultRead) { |
| mApp->drawWithColor(kDrawColorRed); |
| mApp->verifySwappedColor(kDrawColorRed); |
| |
| // Color should not be affected by the draw to non-default |
| // draw/read framebuffers. |
| // (we preserve the previous contents of the surface in |
| // SampleApplication::drawOnce) |
| mApp->setNonDefaultDrawFbo(); |
| mApp->setNonDefaultReadFbo(); |
| |
| mApp->drawWithColor(kDrawColorGreen); |
| mApp->verifySwappedColor(kDrawColorRed); |
| } |
| |
| TEST_P(NonDefaultFramebufferBlit, DefaultDrawNonDefaultRead) { |
| mApp->drawWithColor(kDrawColorRed); |
| mApp->verifySwappedColor(kDrawColorRed); |
| |
| // Bug: 110996998 |
| // Draw to default framebuffer, and have a non-default |
| // read framebuffer bound. Color should show up |
| mApp->setNonDefaultReadFbo(); |
| |
| mApp->drawWithColor(kDrawColorGreen); |
| mApp->verifySwappedColor(kDrawColorGreen); |
| } |
| |
| TEST_P(NonDefaultFramebufferBlit, NonDefaultDrawDefaultRead) { |
| mApp->drawWithColor(kDrawColorRed); |
| mApp->verifySwappedColor(kDrawColorRed); |
| |
| // Draw to non-default framebuffer, and have the default |
| // read framebuffer bound. Color should not show up. |
| // (we preserve the previous contents of the surface in |
| // SampleApplication::drawOnce) |
| mApp->setNonDefaultDrawFbo(); |
| |
| mApp->drawWithColor(kDrawColorGreen); |
| mApp->verifySwappedColor(kDrawColorRed); |
| } |
| |
| // Test blitting both with and without the fast blit path. |
| INSTANTIATE_TEST_SUITE_P(DefaultFramebufferBlitTest, |
| NonDefaultFramebufferBlit, |
| testing::Values( |
| ClearColorParam(GLESApi_3_0, true))); |
| |
| } // namespace |
| } // namespace gfxstream |