// 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 "GLSnapshotTesting.h" #include "apigen-codec-common/glUtils.h" #include #include namespace gfxstream { namespace gl { namespace { struct GlFramebufferAttachment { GLenum type; GLuint name; GLenum textureLevel; GLenum textureCubeMapFace; }; struct GlFramebufferObjectState { std::map attachments; }; class SnapshotGlFramebufferObjectTest : public SnapshotPreserveTest { public: void defaultStateCheck() override { EXPECT_EQ(GL_FALSE, gl->glIsFramebuffer(m_framebuffer_name)); EXPECT_TRUE(compareGlobalGlInt(gl, GL_FRAMEBUFFER_BINDING, 0)); } void changedStateCheck() override { EXPECT_EQ(GL_TRUE, gl->glIsFramebuffer(m_framebuffer_name)); EXPECT_TRUE(compareGlobalGlInt(gl, GL_FRAMEBUFFER_BINDING, m_framebuffer_name)); // don't lose current framebuffer binding GLint currentBind; gl->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tBind); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); for (auto& pair : m_state.attachments) { const GLenum& attachment = pair.first; GlFramebufferAttachment& expected = pair.second; GlFramebufferAttachment current = {}; gl->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_name); gl->glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint*)¤t.type); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); if (current.type != GL_NONE) { gl->glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint*)¤t.name); if (current.type == GL_TEXTURE) { gl->glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, (GLint*)¤t.textureLevel); gl->glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, (GLint*)¤t.textureCubeMapFace); } } EXPECT_EQ(expected.type, current.type); EXPECT_EQ(expected.name, current.name); EXPECT_EQ(expected.textureLevel, current.textureLevel); EXPECT_EQ(expected.textureCubeMapFace, current.textureCubeMapFace); } // restore framebuffer binding gl->glBindFramebuffer(GL_FRAMEBUFFER, currentBind); } void stateChange() override { gl->glGenFramebuffers(1, &m_framebuffer_name); gl->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_name); m_state_changer(); } void setStateChanger(std::function changer) { m_state_changer = changer; } protected: GLuint m_framebuffer_name = 0; GlFramebufferObjectState m_state = {}; std::function m_state_changer = [] {}; }; TEST_F(SnapshotGlFramebufferObjectTest, CreateAndBind) { doCheckedSnapshot(); } TEST_F(SnapshotGlFramebufferObjectTest, BindDepthRenderbuffer) { setStateChanger([this] { GLuint renderbuffer; gl->glGenRenderbuffers(1, &renderbuffer); gl->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); m_state.attachments[GL_DEPTH_ATTACHMENT] = {GL_RENDERBUFFER, renderbuffer, 0, 0}; }); doCheckedSnapshot(); } TEST_F(SnapshotGlFramebufferObjectTest, BindStencilTextureCubeFace) { setStateChanger([this] { GLuint texture; gl->glGenTextures(1, &texture); gl->glBindTexture(GL_TEXTURE_CUBE_MAP, texture); gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texture, 0); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); m_state.attachments[GL_STENCIL_ATTACHMENT] = { GL_TEXTURE, texture, 0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X}; }); doCheckedSnapshot(); } TEST_F(SnapshotGlFramebufferObjectTest, BindColor0Texture2D) { setStateChanger([this] { GLuint texture; gl->glGenTextures(1, &texture); gl->glBindTexture(GL_TEXTURE_2D, texture); // In GLES2, mipmap level must be 0 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); m_state.attachments[GL_COLOR_ATTACHMENT0] = {GL_TEXTURE, texture, 0, 0}; }); doCheckedSnapshot(); } } // namespace } // namespace gl } // namespace gfxstream