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