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 emugl {
23
24 struct GlFramebufferAttachment {
25 GLenum type;
26 GLuint name;
27 GLenum textureLevel;
28 GLenum textureCubeMapFace;
29 };
30
31 struct GlFramebufferObjectState {
32 std::map<GLenum, GlFramebufferAttachment> attachments;
33 };
34
35 class SnapshotGlFramebufferObjectTest : public SnapshotPreserveTest {
36 public:
defaultStateCheck()37 void defaultStateCheck() override {
38 EXPECT_EQ(GL_FALSE, gl->glIsFramebuffer(m_framebuffer_name));
39 EXPECT_TRUE(compareGlobalGlInt(gl, GL_FRAMEBUFFER_BINDING, 0));
40 }
41
changedStateCheck()42 void changedStateCheck() override {
43 EXPECT_EQ(GL_TRUE, gl->glIsFramebuffer(m_framebuffer_name));
44 EXPECT_TRUE(compareGlobalGlInt(gl, GL_FRAMEBUFFER_BINDING,
45 m_framebuffer_name));
46
47 // don't lose current framebuffer binding
48 GLint currentBind;
49 gl->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tBind);
50 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
51
52 for (auto& pair : m_state.attachments) {
53 const GLenum& attachment = pair.first;
54 GlFramebufferAttachment& expected = pair.second;
55
56 GlFramebufferAttachment current = {};
57 gl->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_name);
58 gl->glGetFramebufferAttachmentParameteriv(
59 GL_FRAMEBUFFER, attachment,
60 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
61 (GLint*)¤t.type);
62 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
63
64 if (current.type != GL_NONE) {
65 gl->glGetFramebufferAttachmentParameteriv(
66 GL_FRAMEBUFFER, attachment,
67 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
68 (GLint*)¤t.name);
69 if (current.type == GL_TEXTURE) {
70 gl->glGetFramebufferAttachmentParameteriv(
71 GL_FRAMEBUFFER, attachment,
72 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
73 (GLint*)¤t.textureLevel);
74 gl->glGetFramebufferAttachmentParameteriv(
75 GL_FRAMEBUFFER, attachment,
76 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
77 (GLint*)¤t.textureCubeMapFace);
78 }
79 }
80
81 EXPECT_EQ(expected.type, current.type);
82 EXPECT_EQ(expected.name, current.name);
83 EXPECT_EQ(expected.textureLevel, current.textureLevel);
84 EXPECT_EQ(expected.textureCubeMapFace, current.textureCubeMapFace);
85 }
86
87 // restore framebuffer binding
88 gl->glBindFramebuffer(GL_FRAMEBUFFER, currentBind);
89 }
90
stateChange()91 void stateChange() override {
92 gl->glGenFramebuffers(1, &m_framebuffer_name);
93 gl->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer_name);
94
95 m_state_changer();
96 }
97
setStateChanger(std::function<void ()> changer)98 void setStateChanger(std::function<void()> changer) {
99 m_state_changer = changer;
100 }
101
102 protected:
103 GLuint m_framebuffer_name = 0;
104 GlFramebufferObjectState m_state = {};
__anon5319dd090102null105 std::function<void()> m_state_changer = [] {};
106 };
107
TEST_F(SnapshotGlFramebufferObjectTest,CreateAndBind)108 TEST_F(SnapshotGlFramebufferObjectTest, CreateAndBind) {
109 doCheckedSnapshot();
110 }
111
TEST_F(SnapshotGlFramebufferObjectTest,BindDepthRenderbuffer)112 TEST_F(SnapshotGlFramebufferObjectTest, BindDepthRenderbuffer) {
113 setStateChanger([this] {
114 GLuint renderbuffer;
115 gl->glGenRenderbuffers(1, &renderbuffer);
116 gl->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
117 gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
118 GL_RENDERBUFFER, renderbuffer);
119 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
120
121 m_state.attachments[GL_DEPTH_ATTACHMENT] = {GL_RENDERBUFFER,
122 renderbuffer, 0, 0};
123 });
124 doCheckedSnapshot();
125 }
126
TEST_F(SnapshotGlFramebufferObjectTest,BindStencilTextureCubeFace)127 TEST_F(SnapshotGlFramebufferObjectTest, BindStencilTextureCubeFace) {
128 setStateChanger([this] {
129 GLuint texture;
130 gl->glGenTextures(1, &texture);
131 gl->glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
132 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
133 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texture, 0);
134 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
135
136 m_state.attachments[GL_STENCIL_ATTACHMENT] = {
137 GL_TEXTURE, texture, 0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X};
138 });
139 doCheckedSnapshot();
140 }
141
TEST_F(SnapshotGlFramebufferObjectTest,BindColor0Texture2D)142 TEST_F(SnapshotGlFramebufferObjectTest, BindColor0Texture2D) {
143 setStateChanger([this] {
144 GLuint texture;
145 gl->glGenTextures(1, &texture);
146 gl->glBindTexture(GL_TEXTURE_2D, texture);
147 // In GLES2, mipmap level must be 0
148 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
149 GL_TEXTURE_2D, texture, 0);
150 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
151
152 m_state.attachments[GL_COLOR_ATTACHMENT0] = {GL_TEXTURE, texture, 0, 0};
153 });
154 doCheckedSnapshot();
155 }
156
157 } // namespace emugl
158