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 "GLSnapshotTestStateUtils.h"
16 #include "GLSnapshotTesting.h"
17 #include "OpenGLTestContext.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include <map>
22 
23 namespace gfxstream {
24 namespace gl {
25 namespace {
26 
27 static const GLenum kGLES2GlobalBufferBindings[] = {
28         GL_ARRAY_BUFFER_BINDING, GL_ELEMENT_ARRAY_BUFFER_BINDING};
29 // Buffers could also be bound with vertex attribute arrays.
30 
31 class SnapshotGlBufferObjectsTest : public SnapshotPreserveTest {
32 public:
defaultStateCheck()33     void defaultStateCheck() override {
34         for (GLenum bindTarget : kGLES2GlobalBufferBindings) {
35             EXPECT_TRUE(compareGlobalGlInt(gl, bindTarget, 0))
36                     << "no global buffer object bindings are bound by default";
37         }
38         for (auto& it : m_buffers_data) {
39             EXPECT_EQ(GL_FALSE, gl->glIsBuffer(it.first))
40                     << "test-added buffer objects should not exist by default";
41         }
42     }
43 
changedStateCheck()44     void changedStateCheck() override {
45         // Check that right buffers are bound
46         for (auto& it : m_bindings) {
47             GLenum boundTarget;
48             switch (it.first) {
49                 case GL_ARRAY_BUFFER:
50                     boundTarget = GL_ARRAY_BUFFER_BINDING;
51                     break;
52                 case GL_ELEMENT_ARRAY_BUFFER:
53                     boundTarget = GL_ELEMENT_ARRAY_BUFFER_BINDING;
54                     break;
55                 default:
56                     FAIL() << "Unknown binding location " << it.first;
57             }
58 
59             EXPECT_TRUE(compareGlobalGlInt(gl, boundTarget, it.second))
60                     << "buffer binding " << describeGlEnum(boundTarget)
61                     << " should be bound with " << it.second;
62         }
63 
64         // Check that all buffers have the correct attributes
65         for (auto& it : m_buffers_data) {
66             checkBufferData(it.first, it.second);
67         }
68     }
69 
stateChange()70     void stateChange() override { m_buffer_state_change(); }
71 
72     // Creates a buffer with the properties in |data| and records its state so
73     // it can be checked for preservation after a snapshot.
addBuffer(GlBufferData data)74     GLuint addBuffer(GlBufferData data) {
75         GLuint name = createBuffer(gl, data);
76         m_buffers_data[name] = data;
77         return name;
78     }
79 
80     // Binds a buffer and records the binding to be checked for preservation
81     // after a snapshot.
bindBuffer(GLenum binding,GLuint buffer)82     void bindBuffer(GLenum binding, GLuint buffer) {
83         gl->glBindBuffer(binding, buffer);
84         EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
85 
86         m_bindings[binding] = buffer;
87     }
88 
setObjectStateChange(std::function<void ()> func)89     void setObjectStateChange(std::function<void()> func) {
90         m_buffer_state_change = func;
91     }
92 
93 protected:
checkBufferData(GLuint name,GlBufferData data)94     void checkBufferData(GLuint name, GlBufferData data) {
95         SCOPED_TRACE("checking data for buffer " + std::to_string(name));
96         EXPECT_EQ(GL_TRUE, gl->glIsBuffer(name));
97 
98         // We bind to GL_ARRAY_BUFFER in order to read buffer data,
99         // so let's hold on to what the old binding was so we can restore it
100         GLuint currentArrayBuffer;
101         gl->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&currentArrayBuffer);
102         EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
103 
104         gl->glBindBuffer(GL_ARRAY_BUFFER, name);
105         EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
106         EXPECT_TRUE(compareBufferParameter(GL_ARRAY_BUFFER, GL_BUFFER_SIZE,
107                                            (GLint)data.size));
108         EXPECT_TRUE(compareBufferParameter(GL_ARRAY_BUFFER, GL_BUFFER_USAGE,
109                                            (GLint)data.usage));
110         // TODO(benzene): compare actual buffer contents?
111         // in GLES2 there doesn't seem to be a way to directly read the buffer
112         // contents
113 
114         // Restore the old binding
115         gl->glBindBuffer(GL_ARRAY_BUFFER, currentArrayBuffer);
116         EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
117     }
118 
compareBufferParameter(GLenum target,GLenum paramName,GLint expected)119     testing::AssertionResult compareBufferParameter(GLenum target,
120                                                     GLenum paramName,
121                                                     GLint expected) {
122         GLint value;
123         gl->glGetBufferParameteriv(target, paramName, &value);
124         EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
125         return compareValue<GLint>(
126                 expected, value,
127                 "mismatch on parameter " + describeGlEnum(paramName) +
128                         " for buffer bound to " + describeGlEnum(target));
129     }
130 
131     std::map<GLenum, GLuint> m_bindings;
132     std::map<GLuint, GlBufferData> m_buffers_data;
__anon126380d70202null133     std::function<void()> m_buffer_state_change = [] {};
134 };
135 
TEST_F(SnapshotGlBufferObjectsTest,BindArrayAndElementBuffers)136 TEST_F(SnapshotGlBufferObjectsTest, BindArrayAndElementBuffers) {
137     setObjectStateChange([this] {
138         GlBufferData arrayData = {128, nullptr, GL_STATIC_DRAW};
139         GlBufferData elementArrayData = {256, nullptr, GL_DYNAMIC_DRAW};
140         GLuint arrayBuff = addBuffer(arrayData);
141         GLuint elementArrayBuff = addBuffer(elementArrayData);
142         bindBuffer(GL_ARRAY_BUFFER, arrayBuff);
143         bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuff);
144     });
145     doCheckedSnapshot();
146 }
147 
148 }  // namespace
149 }  // namespace gl
150 }  // namespace gfxstream
151