blob: ac979d66e3edba56958eb1ca61b00981a0c78c5c [file] [log] [blame]
// 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 <gtest/gtest.h>
#include <memory>
#include <vector>
namespace gfxstream {
namespace gl {
struct GlValues {
std::vector<GLint> ints;
std::vector<GLfloat> 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 <class T>
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 <class T>
testing::AssertionResult compareVector(
const std::vector<T>& expected,
const std::vector<T>& 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<GLboolean>& expected,
GLuint size = 0);
testing::AssertionResult compareGlobalGlBooleanv_i(
const GLESv2Dispatch* gl,
GLenum name,
GLuint index,
const std::vector<GLboolean>& 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<GLint>& expected,
GLuint size = 0);
testing::AssertionResult compareGlobalGlIntv_i(const GLESv2Dispatch* gl,
GLenum name,
GLuint index,
const std::vector<GLint>& 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<GLfloat>& 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<void()> 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<Foo> {
// 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 T>
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<T>(new T(defaultValue));
m_changed_value = std::unique_ptr<T>(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<T> m_default_value;
std::unique_ptr<T> m_changed_value;
};
} // namespace gl
} // namespace gfxstream