// 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. #pragma once #include "aemu/base/files/PathUtils.h" #include "aemu/base/system/System.h" #include "aemu/base/testing/TestSystem.h" #include "OpenGLTestContext.h" #include #include #include namespace gfxstream { namespace gl { struct GlValues { std::vector ints; std::vector floats; }; struct GlBufferData { GLsizeiptr size; GLvoid* bytes; GLenum usage; }; // Capabilities which, according to the GLES2 spec, start disabled. static const GLenum kGLES2CanBeEnabled[] = {GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE, GL_SCISSOR_TEST, GL_STENCIL_TEST}; // Capabilities which, according to the GLES2 spec, start enabled. static const GLenum kGLES2CanBeDisabled[] = {GL_DITHER}; // Modes for CullFace static const GLenum kGLES2CullFaceModes[] = {GL_BACK, GL_FRONT, GL_FRONT_AND_BACK}; // Modes for FrontFace static const GLenum kGLES2FrontFaceModes[] = {GL_CCW, GL_CW}; // Valid Stencil test functions static const GLenum kGLES2StencilFuncs[] = {GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL}; // Valid Stencil test result operations static const GLenum kGLES2StencilOps[] = {GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP}; // Modes for the BlendEquation static const GLenum kGLES2BlendEquations[] = {GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT}; // Valid Blend functions static const GLenum kGLES2BlendFuncs[] = {GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE}; // Valid GENERATE_MIPMAP_HINT values static const GLenum kGLES2GenerateMipmapHints[] = {GL_DONT_CARE, GL_FASTEST, GL_NICEST}; // Returns a string useful for failure messages describing |enumValue|. std::string describeGlEnum(GLenum enumValue); // For building other compare functions which return AssertionResult. // Compares an |actual| against an |expected| value. Returns a failure values // do not match; provide |description| to attach details to the failure message. template testing::AssertionResult compareValue(T expected, T actual, const std::string& description = ""); // Compares a global GL value, known by |name| and retrieved as a boolean, // against an |expected| value. testing::AssertionResult compareGlobalGlBoolean(const GLESv2Dispatch* gl, GLenum name, GLboolean expected); // Compares a global GL value, known by |name| and retrieved as an integer, // against an |expected| value. testing::AssertionResult compareGlobalGlInt(const GLESv2Dispatch* gl, GLenum name, GLint expected); testing::AssertionResult compareGlobalGlInt_i(const GLESv2Dispatch* gl, GLenum name, GLuint index, GLint expected); // Compares a global GL value, known by |name| and retrieved as a float, against // an |expected| value. testing::AssertionResult compareGlobalGlFloat(const GLESv2Dispatch* gl, GLenum name, GLfloat expected); // For building other compare functions which return AssertionResult. // Compare the values at each index of a vector |actual| against an |expected|. // Returns a failure if any values are mismatched; provide |description| to // attach details to the failure message. // |actual| is allowed to contain more elements than |expected|. template testing::AssertionResult compareVector( const std::vector& expected, const std::vector& actual, const std::string& description = "vector"); // Compares a vector of global GL values, known by |name| and retrieved as a // boolean array, against |expected| values. // Specify |size| if more space is needed than the size of |expected|. testing::AssertionResult compareGlobalGlBooleanv( const GLESv2Dispatch* gl, GLenum name, const std::vector& expected, GLuint size = 0); testing::AssertionResult compareGlobalGlBooleanv_i( const GLESv2Dispatch* gl, GLenum name, GLuint index, const std::vector& expected, GLuint size = 0); // Compares a vector of global GL values, known by |name| and retrieved as an // integer array, against |expected| values. // Specify |size| if more space is needed than the size of |expected|. testing::AssertionResult compareGlobalGlIntv(const GLESv2Dispatch* gl, GLenum name, const std::vector& expected, GLuint size = 0); testing::AssertionResult compareGlobalGlIntv_i(const GLESv2Dispatch* gl, GLenum name, GLuint index, const std::vector& expected, GLuint size = 0); // Compares a vector of global GL values, known by |name| and retrieved as a // float array, against |expected| values. // Specify |size| if more space is needed than the size of |expected|. testing::AssertionResult compareGlobalGlFloatv( const GLESv2Dispatch* gl, GLenum name, const std::vector& expected, GLuint size = 0); // SnapshotTest - A helper class for performing a test related to saving or // loading GL translator snapshots. As a test fixture, its setup will prepare a // fresh GL state and paths for temporary snapshot files. // // doSnapshot saves a snapshot, clears the GL state, then loads the snapshot. // saveSnapshot and loadSnapshot can be used to perform saves and loads // independently. // // Usage example: // TEST_F(SnapshotTest, PreserveFooBar) { // // clean GL state is ready // EXPECT_TRUE(fooBarState()); // modifyGlStateFooBar(); // EXPECT_FALSE(fooBarState()); // GL state has been changed // doSnapshot(); // saves, resets, and reloads the state // EXPECT_FALSE(fooBarState()); // Snapshot preserved the state change // } // class SnapshotTest : public gfxstream::gl::GLTest { public: SnapshotTest() = default; void SetUp() override; // Mimics FrameBuffer.onSave, with fewer objects to manage. // |streamFile| is a filename into which the snapshot will be saved. // |textureFile| is a filename into which the textures will be saved. void saveSnapshot(const std::string streamFile, const std::string textureFile); // Mimics FrameBuffer.onLoad, with fewer objects to manage. // Assumes that a valid display is present. // |streamFile| is a filename from which the snapshot will be loaded. // |textureFile| is a filename from which the textures will be loaded. void loadSnapshot(const std::string streamFile, const std::string textureFile); // Performs a teardown and reset of graphics objects in preparation for // a snapshot load. void preloadReset(); // Mimics saving and then loading a graphics snapshot. // To verify that state has been reset to some default before the load, // assertions can be performed in |preloadCheck|. void doSnapshot(std::function preloadCheck); protected: android::base::TestSystem mTestSystem; std::string mSnapshotPath = {}; }; // SnapshotPreserveTest - A helper class building on SnapshotTest for granular // testing of the GL snapshot. This is specifically for the common case where a // piece of GL state has a known default, and our test aims to verify that the // snapshot preserves this piece of state when it has been changed from the // default. // // This acts as an abstract class; implementations should override the state // check state change functions to perform the assertions and operations // relevant to the part of GL state that they are testing. // doCheckedSnapshot can be but does not need to be overwritten. It performs the // following: // - check for default state // - make state changes, check that the state changes are in effect // - save a snapshot, reset the GL state, then check for default state // - load the snapshot, check that the state changes are in effect again // // Usage example with a subclass: // class SnapshotEnableFooTest : public SnapshotPreserveTest { // void defaultStateCheck() override { EXPECT_FALSE(isFooEnabled()); } // void changedStateCheck() override { EXPECT_TRUE(isFooEnabled()); } // void stateChange() override { enableFoo(); } // }; // TEST_F(SnapshotEnableFooTest, PreserveFooEnable) { // doCheckedSnapshot(); // } // class SnapshotPreserveTest : public SnapshotTest { public: // Asserts that we are working from a clean starting state. virtual void defaultStateCheck() { ADD_FAILURE() << "Snapshot test needs a default state check function."; } // Asserts that any expected changes to state have occurred. virtual void changedStateCheck() { ADD_FAILURE() << "Snapshot test needs a post-change state check function."; } // Modifies the state. virtual void stateChange() { ADD_FAILURE() << "Snapshot test needs a state-changer function."; } // Sets up a non-default state and asserts that a snapshot preserves it. virtual void doCheckedSnapshot(); }; // SnapshotSetValueTest - A helper class for testing preservation of pieces of // GL state where default and changed state checks are comparisons against the // same type of expected reference value. // // The expected |m_default_value| and |m_changed_value| should be set before // a checked snapshot is attempted. // // Usage example with a subclass: // class SnapshotSetFooTest : public SnapshotSetValueTest { // void stateCheck(Foo expected) { EXPECT_EQ(expected, getFoo()); } // void stateChange() override { setFoo(*m_changed_value); } // }; // TEST_F(SnapshotSetFooTest, SetFooValue) { // setExpectedValues(kFooDefaultValue, kFooTestValue); // doCheckedSnapshot(); // } // template class SnapshotSetValueTest : public SnapshotPreserveTest { public: // Configures the test to assert against values which it should consider // default and values which it should expect after changes. void setExpectedValues(T defaultValue, T changedValue) { m_default_value = std::unique_ptr(new T(defaultValue)); m_changed_value = std::unique_ptr(new T(changedValue)); } // Checks part of state against an expected value. virtual void stateCheck(T expected) { ADD_FAILURE() << "Snapshot test needs a state-check function."; }; void defaultStateCheck() override { stateCheck(*m_default_value); } void changedStateCheck() override { stateCheck(*m_changed_value); } void doCheckedSnapshot() override { if (m_default_value == nullptr || m_changed_value == nullptr) { FAIL() << "Snapshot test not provided expected values."; } SnapshotPreserveTest::doCheckedSnapshot(); } protected: std::unique_ptr m_default_value; std::unique_ptr m_changed_value; }; } // namespace gl } // namespace gfxstream