mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
metal: initial work on windowing and instance creation
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "Video.h"
|
||||
#include "Text.h"
|
||||
#include "common/deprecation.h"
|
||||
#include "common/config.h"
|
||||
|
||||
// C++
|
||||
#include <algorithm>
|
||||
@@ -106,6 +107,36 @@ love::Type Graphics::type("graphics", &Module::type);
|
||||
|
||||
Graphics::DefaultShaderCode Graphics::defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
|
||||
namespace opengl { extern love::graphics::Graphics *createInstance(); }
|
||||
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
|
||||
namespace metal { extern love::graphics::Graphics *createInstance(); }
|
||||
#endif
|
||||
|
||||
Graphics *Graphics::createInstance(const std::vector<Renderer> &renderers)
|
||||
{
|
||||
Graphics *instance = Module::getInstance<Graphics>(M_GRAPHICS);
|
||||
|
||||
if (instance != nullptr)
|
||||
instance->retain();
|
||||
else
|
||||
{
|
||||
for (auto renderer : renderers)
|
||||
{
|
||||
if (renderer == RENDERER_OPENGL)
|
||||
instance = opengl::createInstance();
|
||||
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
|
||||
if (renderer == RENDERER_METAL)
|
||||
instance = metal::createInstance();
|
||||
#endif
|
||||
|
||||
if (instance != nullptr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
Graphics::Graphics()
|
||||
: width(0)
|
||||
, height(0)
|
||||
@@ -241,7 +272,7 @@ ShaderStage *Graphics::newShaderStage(ShaderStage::StageType stage, const std::s
|
||||
|
||||
if (s == nullptr)
|
||||
{
|
||||
s = newShaderStageInternal(stage, cachekey, source, getRenderer() == RENDERER_OPENGLES);
|
||||
s = newShaderStageInternal(stage, cachekey, source, usesGLSLES());
|
||||
if (!cachekey.empty())
|
||||
cachedShaderStages[stage][cachekey] = s;
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
enum Renderer
|
||||
{
|
||||
RENDERER_OPENGL = 0,
|
||||
RENDERER_OPENGLES,
|
||||
RENDERER_METAL,
|
||||
RENDERER_MAX_ENUM
|
||||
};
|
||||
|
||||
@@ -797,6 +797,11 @@ public:
|
||||
**/
|
||||
virtual Renderer getRenderer() const = 0;
|
||||
|
||||
/**
|
||||
* Whether shaders will use GLSL ES or not (mobile shaders).
|
||||
**/
|
||||
virtual bool usesGLSLES() const = 0;
|
||||
|
||||
/**
|
||||
* Returns system-dependent renderer information.
|
||||
* Returned strings can vary greatly between systems! Do not rely on it for
|
||||
@@ -853,6 +858,8 @@ public:
|
||||
return (T *) scratchBuffer.data();
|
||||
}
|
||||
|
||||
static Graphics *createInstance(const std::vector<Renderer> &renderers);
|
||||
|
||||
static bool getConstant(const char *in, DrawMode &out);
|
||||
static bool getConstant(DrawMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(DrawMode);
|
||||
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
bool isCanvasFormatSupported(PixelFormat format, bool readable) const override;
|
||||
bool isImageFormatSupported(PixelFormat format, bool sRGB) const override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
RendererInfo getRendererInfo() const override;
|
||||
|
||||
Shader::Language getShaderLanguageTarget() const override;
|
||||
|
||||
@@ -133,6 +133,22 @@ static MTLBlendFactor getMTLBlendFactor(BlendFactor factor)
|
||||
return MTLBlendFactorZero;
|
||||
}
|
||||
|
||||
love::graphics::Graphics *createInstance()
|
||||
{
|
||||
love::graphics::Graphics *instance = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
instance = new Graphics();
|
||||
}
|
||||
catch (love::Exception &e)
|
||||
{
|
||||
printf("Cannot create Metal renderer: %s\n", e.what());
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
Graphics::Graphics()
|
||||
: device(nil)
|
||||
, commandQueue(nil)
|
||||
@@ -935,6 +951,30 @@ void Graphics::setBlendState(const BlendState &blend)
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Renderer Graphics::getRenderer() const
|
||||
{
|
||||
return RENDERER_METAL;
|
||||
}
|
||||
|
||||
bool Graphics::usesGLSLES() const
|
||||
{
|
||||
#ifdef LOVE_IOS
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Graphics::RendererInfo Graphics::getRendererInfo() const
|
||||
{
|
||||
RendererInfo info;
|
||||
info.name = "Metal";
|
||||
info.version = "1"; // TODO
|
||||
info.vendor = ""; // TODO
|
||||
info.device = device.name.UTF8String;
|
||||
return info;
|
||||
}
|
||||
|
||||
} // metal
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -88,6 +88,22 @@ static GLenum getGLBlendFactor(BlendFactor factor)
|
||||
return 0;
|
||||
}
|
||||
|
||||
love::graphics::Graphics *createInstance()
|
||||
{
|
||||
love::graphics::Graphics *instance = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
instance = new Graphics();
|
||||
}
|
||||
catch (love::Exception &e)
|
||||
{
|
||||
printf("Cannot create OpenGL renderer: %s\n", e.what());
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
Graphics::Graphics()
|
||||
: windowHasStencil(false)
|
||||
, mainVAO(0)
|
||||
@@ -1322,7 +1338,12 @@ void Graphics::setWireframe(bool enable)
|
||||
|
||||
Graphics::Renderer Graphics::getRenderer() const
|
||||
{
|
||||
return GLAD_ES_VERSION_2_0 ? RENDERER_OPENGLES : RENDERER_OPENGL;
|
||||
return RENDERER_OPENGL;
|
||||
}
|
||||
|
||||
bool Graphics::usesGLSLES() const
|
||||
{
|
||||
return GLAD_ES_VERSION_2_0;
|
||||
}
|
||||
|
||||
Graphics::RendererInfo Graphics::getRendererInfo() const
|
||||
|
||||
@@ -108,6 +108,7 @@ public:
|
||||
bool isCanvasFormatSupported(PixelFormat format, bool readable) const override;
|
||||
bool isImageFormatSupported(PixelFormat format, bool sRGB) const override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
RendererInfo getRendererInfo() const override;
|
||||
|
||||
Shader::Language getShaderLanguageTarget() const override;
|
||||
|
||||
@@ -1363,7 +1363,7 @@ static int w_getShaderSource(lua_State *L, int startidx, bool gles, std::string
|
||||
|
||||
int w_newShader(lua_State *L)
|
||||
{
|
||||
bool gles = instance()->getRenderer() == Graphics::RENDERER_OPENGLES;
|
||||
bool gles = instance()->usesGLSLES();
|
||||
|
||||
std::string vertexsource, pixelsource;
|
||||
w_getShaderSource(L, 1, gles, vertexsource, pixelsource);
|
||||
@@ -3146,13 +3146,22 @@ static const lua_CFunction types[] =
|
||||
|
||||
extern "C" int luaopen_love_graphics(lua_State *L)
|
||||
{
|
||||
Graphics *instance = instance();
|
||||
Graphics *instance = nullptr;
|
||||
|
||||
{
|
||||
std::vector<Graphics::Renderer> renderers;
|
||||
#if defined(LOVE_MACOS) || defined(LOVE_IOS)
|
||||
renderers.push_back(Graphics::RENDERER_METAL);
|
||||
#endif
|
||||
renderers.push_back(Graphics::RENDERER_OPENGL);
|
||||
instance = Graphics::createInstance(renderers);
|
||||
}
|
||||
|
||||
if (instance == nullptr)
|
||||
{
|
||||
luax_catchexcept(L, [&](){ instance = new love::graphics::opengl::Graphics(); });
|
||||
printf("Cannot create graphics: no supported renderer on this system.\n");
|
||||
return luaL_error(L, "Cannot create graphics: no supported renderer on this system.");
|
||||
}
|
||||
else
|
||||
instance->retain();
|
||||
|
||||
WrappedModule w;
|
||||
w.module = instance;
|
||||
|
||||
Reference in New Issue
Block a user