blob: 2defe4024c2d73d6e7a27f3d9662054615a41ad8 [file] [log] [blame]
/*
* Copyright 2022 Rive
*/
#ifndef TESTING_WINDOW_HPP
#define TESTING_WINDOW_HPP
#include "rive/rive_types.hpp"
#include "rive/enum_bitset.hpp"
#include <memory>
#include <vector>
#include <string>
namespace rive
{
class Renderer;
class Factory;
namespace gpu
{
class RenderContext;
class RenderContextGLImpl;
class RenderTarget;
} // namespace gpu
}; // namespace rive
// Wraps a factory for rive::Renderer and a singleton target for it to render
// into (GL window, HTML canvas, software buffer, etc.):
//
// TestingWindow::Init(type);
// renderer = TestingWindow::Get()->reset(width, height);
// ...
//
class TestingWindow
{
public:
enum class Backend
{
gl,
glatomic,
glcw,
glmsaa,
d3d,
d3datomic,
metal,
metalcw,
metalatomic,
// System default Vulkan driver.
vk,
vkcore, // Vulkan with as few features enabled as possible.
vkcw,
// Vulkan on Metal, aka MoltenVK.
// (defaults to /usr/local/share/vulkan/icd.d/MoltenVK_icd.json if
// VK_ICD_FILENAMES is not set.)
moltenvk,
moltenvkcore,
// Swiftshader, Google's CPU implementation of Vulkan.
// (defaults to ./vk_swiftshader_icd.json if VK_ICD_FILENAMES is not
// set.)
swiftshader,
swiftshadercore,
angle,
anglemsaa,
dawn,
rhi,
coregraphics,
skia,
};
constexpr static bool IsGL(Backend backend)
{
switch (backend)
{
case Backend::gl:
case Backend::glatomic:
case Backend::glcw:
case Backend::glmsaa:
case Backend::angle:
case Backend::anglemsaa:
return true;
case Backend::d3d:
case Backend::d3datomic:
case Backend::metal:
case Backend::metalcw:
case Backend::metalatomic:
case Backend::vk:
case Backend::vkcore:
case Backend::vkcw:
case Backend::moltenvk:
case Backend::moltenvkcore:
case Backend::swiftshader:
case Backend::swiftshadercore:
case Backend::dawn:
case Backend::rhi:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
constexpr static bool IsANGLE(Backend backend)
{
switch (backend)
{
case Backend::angle:
case Backend::anglemsaa:
return true;
case Backend::gl:
case Backend::glatomic:
case Backend::glcw:
case Backend::glmsaa:
case Backend::d3d:
case Backend::d3datomic:
case Backend::metal:
case Backend::metalcw:
case Backend::metalatomic:
case Backend::vk:
case Backend::vkcore:
case Backend::vkcw:
case Backend::moltenvk:
case Backend::moltenvkcore:
case Backend::swiftshader:
case Backend::swiftshadercore:
case Backend::dawn:
case Backend::rhi:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
constexpr static bool IsVulkan(Backend backend)
{
switch (backend)
{
case Backend::vk:
case Backend::vkcore:
case Backend::vkcw:
case Backend::moltenvk:
case Backend::moltenvkcore:
case Backend::swiftshader:
case Backend::swiftshadercore:
return true;
case Backend::gl:
case Backend::glatomic:
case Backend::glcw:
case Backend::glmsaa:
case Backend::d3d:
case Backend::d3datomic:
case Backend::metal:
case Backend::metalcw:
case Backend::metalatomic:
case Backend::dawn:
case Backend::angle:
case Backend::anglemsaa:
case Backend::rhi:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
constexpr static bool IsAtomic(Backend backend)
{
switch (backend)
{
case Backend::glatomic:
case Backend::glcw:
case Backend::d3datomic:
case Backend::metalatomic:
case Backend::rhi:
case Backend::vkcore:
case Backend::vkcw:
case Backend::moltenvkcore:
case Backend::swiftshadercore:
return true;
case Backend::gl:
case Backend::glmsaa:
case Backend::d3d:
case Backend::metal:
case Backend::metalcw:
case Backend::vk:
case Backend::moltenvk:
case Backend::swiftshader:
case Backend::angle:
case Backend::anglemsaa:
case Backend::dawn:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
constexpr static bool IsCore(Backend backend)
{
switch (backend)
{
case Backend::vkcore:
case Backend::moltenvkcore:
case Backend::swiftshadercore:
return true;
case Backend::glatomic:
case Backend::glcw:
case Backend::d3datomic:
case Backend::metalatomic:
case Backend::gl:
case Backend::glmsaa:
case Backend::d3d:
case Backend::metal:
case Backend::metalcw:
case Backend::vk:
case Backend::vkcw:
case Backend::moltenvk:
case Backend::swiftshader:
case Backend::angle:
case Backend::anglemsaa:
case Backend::dawn:
case Backend::rhi:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
constexpr static bool IsMSAA(Backend backend)
{
switch (backend)
{
case Backend::glmsaa:
case Backend::anglemsaa:
return true;
case Backend::glatomic:
case Backend::glcw:
case Backend::d3datomic:
case Backend::metalatomic:
case Backend::vkcore:
case Backend::vkcw:
case Backend::moltenvkcore:
case Backend::swiftshadercore:
case Backend::gl:
case Backend::d3d:
case Backend::metal:
case Backend::metalcw:
case Backend::vk:
case Backend::moltenvk:
case Backend::swiftshader:
case Backend::angle:
case Backend::dawn:
case Backend::rhi:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
constexpr static bool IsClockwiseFill(Backend backend)
{
switch (backend)
{
case Backend::glcw:
case Backend::metalcw:
case Backend::vkcw:
return true;
case Backend::glatomic:
case Backend::glmsaa:
case Backend::d3datomic:
case Backend::metalatomic:
case Backend::vkcore:
case Backend::moltenvkcore:
case Backend::swiftshadercore:
case Backend::gl:
case Backend::d3d:
case Backend::metal:
case Backend::vk:
case Backend::moltenvk:
case Backend::swiftshader:
case Backend::angle:
case Backend::anglemsaa:
case Backend::dawn:
case Backend::rhi:
case Backend::coregraphics:
case Backend::skia:
return false;
}
RIVE_UNREACHABLE();
}
enum class RendererFlags
{
none = 0,
useMSAA = 1 << 0,
disableRasterOrdering = 1 << 1,
clockwiseFillOverride = 1 << 2,
};
enum class Visibility
{
headless,
window,
fullscreen,
};
static const char* BackendName(Backend);
static Backend ParseBackend(const char* name, std::string* gpuNameFilter);
static TestingWindow* Init(Backend,
Visibility,
const std::string& gpuNameFilter,
void* platformWindow = nullptr);
static TestingWindow* Get();
static void Set(TestingWindow* inWindow);
static void Destroy();
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
virtual rive::Factory* factory() = 0;
virtual void resize(int width, int height)
{
m_width = width;
m_height = height;
}
struct FrameOptions
{
uint32_t clearColor;
bool doClear = true;
bool wireframe = false;
bool clockwiseFillOverride = false;
};
virtual std::unique_ptr<rive::Renderer> beginFrame(const FrameOptions&) = 0;
virtual void endFrame(std::vector<uint8_t>* pixelData = nullptr) = 0;
// For testing directly on RenderContext.
virtual rive::gpu::RenderContext* renderContext() const { return nullptr; }
virtual rive::gpu::RenderContextGLImpl* renderContextGLImpl() const
{
return nullptr;
}
virtual rive::gpu::RenderTarget* renderTarget() const { return nullptr; }
// For testing render pass breaks. Caller must call
// renderContext()->beginFrame() again.
virtual void flushPLSContext() {}
// Blocks until a key is pressed.
virtual bool peekKey(char& key) { return false; }
virtual char getKey()
{
fprintf(stderr, "TestingWindow::getKey not implemented.");
abort();
}
virtual bool shouldQuit() const { return false; }
virtual ~TestingWindow() {}
protected:
uint32_t m_width = 0;
uint32_t m_height = 0;
private:
static TestingWindow* MakeGLFW(Backend, Visibility);
static TestingWindow* MakeEGL(Backend, void* platformWindow);
#ifdef _WIN32
static TestingWindow* MakeD3D(Visibility);
#endif
#if defined(__APPLE__) && !defined(RIVE_UNREAL)
static TestingWindow* MakeMetalTexture();
#endif
static TestingWindow* MakeCoreGraphics();
static TestingWindow* MakeFiddleContext(Backend,
Visibility,
const char* gpuNameFilter,
void* platformWindow);
static TestingWindow* MakeVulkanTexture(bool coreFeaturesOnly,
bool clockwiseFill,
const char* gpuNameFilter);
static TestingWindow* MakeAndroidVulkan(void* platformWindow,
bool coreFeaturesOnly,
bool clockwiseFill);
static TestingWindow* MakeSkia();
};
RIVE_MAKE_ENUM_BITSET(TestingWindow::RendererFlags);
#endif