blob: 7af41742785e5e2c8b8b90c2e78b45e276ea4334 [file] [log] [blame]
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Feature.h: Definition of structs to hold feature/workaround information.
//
#ifndef ANGLE_PLATFORM_FEATURE_H_
#define ANGLE_PLATFORM_FEATURE_H_
#include <map>
#include <string>
#include <vector>
#define ANGLE_FEATURE_CONDITION(set, feature, cond) \
do \
{ \
set->feature.enabled = cond; \
set->feature.condition = ANGLE_STRINGIFY(cond); \
} while (0)
namespace angle
{
enum class FeatureCategory
{
FrontendWorkarounds,
OpenGLWorkarounds,
D3DWorkarounds,
D3DCompilerWorkarounds,
VulkanWorkarounds,
VulkanFeatures,
MetalFeatures,
};
constexpr char kFeatureCategoryFrontendWorkarounds[] = "Frontend workarounds";
constexpr char kFeatureCategoryOpenGLWorkarounds[] = "OpenGL workarounds";
constexpr char kFeatureCategoryD3DWorkarounds[] = "D3D workarounds";
constexpr char kFeatureCategoryD3DCompilerWorkarounds[] = "D3D compiler workarounds";
constexpr char kFeatureCategoryVulkanWorkarounds[] = "Vulkan workarounds";
constexpr char kFeatureCategoryVulkanFeatures[] = "Vulkan features";
constexpr char kFeatureCategoryMetalFeatures[] = "Metal features";
constexpr char kFeatureCategoryUnknown[] = "Unknown";
inline const char *FeatureCategoryToString(const FeatureCategory &fc)
{
switch (fc)
{
case FeatureCategory::FrontendWorkarounds:
return kFeatureCategoryFrontendWorkarounds;
break;
case FeatureCategory::OpenGLWorkarounds:
return kFeatureCategoryOpenGLWorkarounds;
break;
case FeatureCategory::D3DWorkarounds:
return kFeatureCategoryD3DWorkarounds;
break;
case FeatureCategory::D3DCompilerWorkarounds:
return kFeatureCategoryD3DCompilerWorkarounds;
break;
case FeatureCategory::VulkanWorkarounds:
return kFeatureCategoryVulkanWorkarounds;
break;
case FeatureCategory::VulkanFeatures:
return kFeatureCategoryVulkanFeatures;
break;
case FeatureCategory::MetalFeatures:
return kFeatureCategoryMetalFeatures;
break;
default:
return kFeatureCategoryUnknown;
break;
}
}
constexpr char kFeatureStatusEnabled[] = "enabled";
constexpr char kFeatureStatusDisabled[] = "disabled";
inline const char *FeatureStatusToString(const bool &status)
{
if (status)
{
return kFeatureStatusEnabled;
}
return kFeatureStatusDisabled;
}
struct Feature;
using FeatureMap = std::map<std::string, Feature *>;
using FeatureList = std::vector<const Feature *>;
struct Feature
{
Feature(const Feature &other);
Feature(const char *name,
const FeatureCategory &category,
const char *description,
FeatureMap *const mapPtr,
const char *bug);
~Feature();
// The name of the workaround, lowercase, camel_case
const char *const name;
// The category that the workaround belongs to. Eg. "Vulkan workarounds"
const FeatureCategory category;
// A short description to be read by the user.
const char *const description;
// A link to the bug, if any
const char *const bug;
// Whether the workaround is enabled or not. Determined by heuristics like vendor ID and
// version, but may be overriden to any value.
bool enabled = false;
// A stingified version of the condition used to set 'enabled'. ie "IsNvidia() && IsApple()"
const char *condition;
};
inline Feature::Feature(const Feature &other) = default;
inline Feature::Feature(const char *name,
const FeatureCategory &category,
const char *description,
FeatureMap *const mapPtr,
const char *bug = "")
: name(name),
category(category),
description(description),
bug(bug),
enabled(false),
condition(nullptr)
{
if (mapPtr != nullptr)
{
(*mapPtr)[std::string(name)] = this;
}
}
inline Feature::~Feature() = default;
struct FeatureSetBase
{
public:
FeatureSetBase();
~FeatureSetBase();
private:
// Non-copyable
FeatureSetBase(const FeatureSetBase &other) = delete;
FeatureSetBase &operator=(const FeatureSetBase &other) = delete;
protected:
FeatureMap members = FeatureMap();
public:
void overrideFeatures(const std::vector<std::string> &feature_names, const bool enabled)
{
for (const std::string &name : feature_names)
{
if (members.find(name) != members.end())
{
members[name]->enabled = enabled;
}
}
}
void populateFeatureList(FeatureList *features) const
{
for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++)
{
features->push_back(it->second);
}
}
};
inline FeatureSetBase::FeatureSetBase() = default;
inline FeatureSetBase::~FeatureSetBase() = default;
} // namespace angle
#endif // ANGLE_PLATFORM_WORKAROUND_H_