1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "GLSnapshotTesting.h"
16 #include "apigen-codec-common/glUtils.h"
17
18 #include <gtest/gtest.h>
19
20 #include <map>
21
22 namespace gfxstream {
23 namespace gl {
24 namespace {
25
26 struct GlFramebufferAttachment {
27 GLenum type;
28 GLuint name;
29 GLenum textureLevel;
30 GLenum textureCubeMapFace;
31 };
32
33 struct GlFramebufferObjectState {
34 std::map<GLenum, GlFramebufferAttachment> attachments;
35 };
36
37 class SnapshotGlFramebufferObjectTest : public SnapshotPreserveTest {
38 public:
defaultStateCheck()39 void defaultStateCheck() override {
40 EXPECT_EQ(GL_FALSE, gl->glIsFramebuffer(m_framebuffer_name));
41 EXPECT_TRUE(compareGlobalGlInt(gl, GL_FRAMEBUFFER_BINDING, 0));
42 }
43
changedStateCheck()44 void changedStateCheck() override {
45 EXPECT_EQ(GL_TRUE, gl->glIsFramebuffer(m_framebuffer_name));
46 EXPECT_TRUE(compareGlobalGlInt(gl, GL_FRAMEBUFFER_BINDING,
47 m_framebuffer_name));
48
49 // don't lose current framebuffer binding
50 GLint currentBind;
51 gl->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tBind);
52 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
53
54 for (auto& pair : m_state.attachments) {
55 const GLenum& attachment = pair.first;
56 GlFramebufferAttachment& expected = pair.second;
57
58 GlFramebufferAttachment current = {};
59 gl->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_name);
60 gl->glGetFramebufferAttachmentParameteriv(
61 GL_FRAMEBUFFER, attachment,
62 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
63 (GLint*)¤t.type);
64 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
65
66 if (current.type != GL_NONE) {
67 gl->glGetFramebufferAttachmentParameteriv(
68 GL_FRAMEBUFFER, attachment,
69 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
70 (GLint*)¤t.name);
71 if (current.type == GL_TEXTURE) {
72 gl->glGetFramebufferAttachmentParameteriv(
73 GL_FRAMEBUFFER, attachment,
74 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
75 (GLint*)¤t.textureLevel);
76 gl->glGetFramebufferAttachmentParameteriv(
77 GL_FRAMEBUFFER, attachment,
78 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
79 (GLint*)¤t.textureCubeMapFace);
80 }
81 }
82
83 EXPECT_EQ(expected.type, current.type);
84 EXPECT_EQ(expected.name, current.name);
85 EXPECT_EQ(expected.textureLevel, current.textureLevel);
86 EXPECT_EQ(expected.textureCubeMapFace, current.textureCubeMapFace);
87 }
88
89 // restore framebuffer binding
90 gl->glBindFramebuffer(GL_FRAMEBUFFER, currentBind);
91 }
92
stateChange()93 void stateChange() override {
94 gl->glGenFramebuffers(1, &m_framebuffer_name);
95 gl->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_name);
96
97 m_state_changer();
98 }
99
setStateChanger(std::function<void ()> changer)100 void setStateChanger(std::function<void()> changer) {
101 m_state_changer = changer;
102 }
103
104 protected:
105 GLuint m_framebuffer_name = 0;
106 GlFramebufferObjectState m_state = {};
__anon93d10ad60202null107 std::function<void()> m_state_changer = [] {};
108 };
109
TEST_F(SnapshotGlFramebufferObjectTest,CreateAndBind)110 TEST_F(SnapshotGlFramebufferObjectTest, CreateAndBind) {
111 doCheckedSnapshot();
112 }
113
TEST_F(SnapshotGlFramebufferObjectTest,BindDepthRenderbuffer)114 TEST_F(SnapshotGlFramebufferObjectTest, BindDepthRenderbuffer) {
115 setStateChanger([this] {
116 GLuint renderbuffer;
117 gl->glGenRenderbuffers(1, &renderbuffer);
118 gl->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
119 gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
120 GL_RENDERBUFFER, renderbuffer);
121 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
122
123 m_state.attachments[GL_DEPTH_ATTACHMENT] = {GL_RENDERBUFFER,
124 renderbuffer, 0, 0};
125 });
126 doCheckedSnapshot();
127 }
128
TEST_F(SnapshotGlFramebufferObjectTest,BindStencilTextureCubeFace)129 TEST_F(SnapshotGlFramebufferObjectTest, BindStencilTextureCubeFace) {
130 setStateChanger([this] {
131 GLuint texture;
132 gl->glGenTextures(1, &texture);
133 gl->glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
134 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
135 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texture, 0);
136 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
137
138 m_state.attachments[GL_STENCIL_ATTACHMENT] = {
139 GL_TEXTURE, texture, 0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X};
140 });
141 doCheckedSnapshot();
142 }
143
TEST_F(SnapshotGlFramebufferObjectTest,BindColor0Texture2D)144 TEST_F(SnapshotGlFramebufferObjectTest, BindColor0Texture2D) {
145 setStateChanger([this] {
146 GLuint texture;
147 gl->glGenTextures(1, &texture);
148 gl->glBindTexture(GL_TEXTURE_2D, texture);
149 // In GLES2, mipmap level must be 0
150 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
151 GL_TEXTURE_2D, texture, 0);
152 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
153
154 m_state.attachments[GL_COLOR_ATTACHMENT0] = {GL_TEXTURE, texture, 0, 0};
155 });
156 doCheckedSnapshot();
157 }
158
159 } // namespace
160 } // namespace gl
161 } // namespace gfxstream
162