// 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 "GLSnapshotTestStateUtils.h" #include "GLSnapshotTesting.h" #include "OpenGLTestContext.h" #include #include namespace gfxstream { namespace gl { namespace { static const GLenum kGLES2GlobalBufferBindings[] = { GL_ARRAY_BUFFER_BINDING, GL_ELEMENT_ARRAY_BUFFER_BINDING}; // Buffers could also be bound with vertex attribute arrays. class SnapshotGlBufferObjectsTest : public SnapshotPreserveTest { public: void defaultStateCheck() override { for (GLenum bindTarget : kGLES2GlobalBufferBindings) { EXPECT_TRUE(compareGlobalGlInt(gl, bindTarget, 0)) << "no global buffer object bindings are bound by default"; } for (auto& it : m_buffers_data) { EXPECT_EQ(GL_FALSE, gl->glIsBuffer(it.first)) << "test-added buffer objects should not exist by default"; } } void changedStateCheck() override { // Check that right buffers are bound for (auto& it : m_bindings) { GLenum boundTarget; switch (it.first) { case GL_ARRAY_BUFFER: boundTarget = GL_ARRAY_BUFFER_BINDING; break; case GL_ELEMENT_ARRAY_BUFFER: boundTarget = GL_ELEMENT_ARRAY_BUFFER_BINDING; break; default: FAIL() << "Unknown binding location " << it.first; } EXPECT_TRUE(compareGlobalGlInt(gl, boundTarget, it.second)) << "buffer binding " << describeGlEnum(boundTarget) << " should be bound with " << it.second; } // Check that all buffers have the correct attributes for (auto& it : m_buffers_data) { checkBufferData(it.first, it.second); } } void stateChange() override { m_buffer_state_change(); } // Creates a buffer with the properties in |data| and records its state so // it can be checked for preservation after a snapshot. GLuint addBuffer(GlBufferData data) { GLuint name = createBuffer(gl, data); m_buffers_data[name] = data; return name; } // Binds a buffer and records the binding to be checked for preservation // after a snapshot. void bindBuffer(GLenum binding, GLuint buffer) { gl->glBindBuffer(binding, buffer); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); m_bindings[binding] = buffer; } void setObjectStateChange(std::function func) { m_buffer_state_change = func; } protected: void checkBufferData(GLuint name, GlBufferData data) { SCOPED_TRACE("checking data for buffer " + std::to_string(name)); EXPECT_EQ(GL_TRUE, gl->glIsBuffer(name)); // We bind to GL_ARRAY_BUFFER in order to read buffer data, // so let's hold on to what the old binding was so we can restore it GLuint currentArrayBuffer; gl->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)¤tArrayBuffer); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); gl->glBindBuffer(GL_ARRAY_BUFFER, name); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); EXPECT_TRUE(compareBufferParameter(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint)data.size)); EXPECT_TRUE(compareBufferParameter(GL_ARRAY_BUFFER, GL_BUFFER_USAGE, (GLint)data.usage)); // TODO(benzene): compare actual buffer contents? // in GLES2 there doesn't seem to be a way to directly read the buffer // contents // Restore the old binding gl->glBindBuffer(GL_ARRAY_BUFFER, currentArrayBuffer); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); } testing::AssertionResult compareBufferParameter(GLenum target, GLenum paramName, GLint expected) { GLint value; gl->glGetBufferParameteriv(target, paramName, &value); EXPECT_EQ(GL_NO_ERROR, gl->glGetError()); return compareValue( expected, value, "mismatch on parameter " + describeGlEnum(paramName) + " for buffer bound to " + describeGlEnum(target)); } std::map m_bindings; std::map m_buffers_data; std::function m_buffer_state_change = [] {}; }; TEST_F(SnapshotGlBufferObjectsTest, BindArrayAndElementBuffers) { setObjectStateChange([this] { GlBufferData arrayData = {128, nullptr, GL_STATIC_DRAW}; GlBufferData elementArrayData = {256, nullptr, GL_DYNAMIC_DRAW}; GLuint arrayBuff = addBuffer(arrayData); GLuint elementArrayBuff = addBuffer(elementArrayData); bindBuffer(GL_ARRAY_BUFFER, arrayBuff); bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuff); }); doCheckedSnapshot(); } } // namespace } // namespace gl } // namespace gfxstream