mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Restructured internal code for graphics capabilities. Added love.graphics.getTextureTypes which returns a table of Texture Type to boolean supported fields.
--HG-- branch : minor
This commit is contained in:
@@ -72,6 +72,7 @@ Canvas::Canvas(const Settings &settings)
|
||||
}
|
||||
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
const Graphics::Capabilities &caps = gfx->getCapabilities();
|
||||
|
||||
if (!gfx->isCanvasFormatSupported(format, readable))
|
||||
{
|
||||
@@ -89,7 +90,7 @@ Canvas::Canvas(const Settings &settings)
|
||||
if (!readable && texType != TEXTURE_2D)
|
||||
throw love::Exception("Non-readable pixel formats are only supported for 2D texture types.");
|
||||
|
||||
if (!gfx->isTextureTypeSupported(texType))
|
||||
if (!caps.textureTypes[texType])
|
||||
{
|
||||
const char *textypestr = "unknown";
|
||||
Texture::getConstant(texType, textypestr);
|
||||
@@ -100,14 +101,14 @@ Canvas::Canvas(const Settings &settings)
|
||||
switch (texType)
|
||||
{
|
||||
case TEXTURE_2D:
|
||||
maxsize = gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE);
|
||||
maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
|
||||
if (pixelWidth > maxsize)
|
||||
throw TextureTooLargeException("width", pixelWidth);
|
||||
else if (pixelHeight > maxsize)
|
||||
throw TextureTooLargeException("height", pixelHeight);
|
||||
break;
|
||||
case TEXTURE_VOLUME:
|
||||
maxsize = gfx->getSystemLimit(Graphics::LIMIT_VOLUME_TEXTURE_SIZE);
|
||||
maxsize = (int) caps.limits[Graphics::LIMIT_VOLUME_TEXTURE_SIZE];
|
||||
if (pixelWidth > maxsize)
|
||||
throw TextureTooLargeException("width", pixelWidth);
|
||||
else if (pixelHeight > maxsize)
|
||||
@@ -116,18 +117,18 @@ Canvas::Canvas(const Settings &settings)
|
||||
throw TextureTooLargeException("depth", depth);
|
||||
break;
|
||||
case TEXTURE_2D_ARRAY:
|
||||
maxsize = gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE);
|
||||
maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
|
||||
if (pixelWidth > maxsize)
|
||||
throw TextureTooLargeException("width", pixelWidth);
|
||||
else if (pixelHeight > maxsize)
|
||||
throw TextureTooLargeException("height", pixelHeight);
|
||||
else if (layers > gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_LAYERS))
|
||||
else if (layers > (int) caps.limits[Graphics::LIMIT_TEXTURE_LAYERS])
|
||||
throw TextureTooLargeException("array layer count", layers);
|
||||
break;
|
||||
case TEXTURE_CUBE:
|
||||
if (pixelWidth != pixelHeight)
|
||||
throw love::Exception("Cubemap textures must have equal width and height.");
|
||||
else if (pixelWidth > gfx->getSystemLimit(Graphics::LIMIT_CUBE_TEXTURE_SIZE))
|
||||
else if (pixelWidth > (int) caps.limits[Graphics::LIMIT_CUBE_TEXTURE_SIZE])
|
||||
throw TextureTooLargeException("width", pixelWidth);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -99,7 +99,10 @@ Font::TextureSize Font::getNextTextureSize() const
|
||||
int maxsize = 2048;
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
maxsize = (int) gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE);
|
||||
{
|
||||
const auto &caps = gfx->getCapabilities();
|
||||
maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
|
||||
}
|
||||
|
||||
int maxwidth = std::min(8192, maxsize);
|
||||
int maxheight = std::min(4096, maxsize);
|
||||
|
||||
@@ -112,6 +112,7 @@ Graphics::Graphics()
|
||||
, streamBufferState()
|
||||
, projectionMatrix()
|
||||
, canvasSwitchCount(0)
|
||||
, capabilities()
|
||||
{
|
||||
transformStack.reserve(16);
|
||||
transformStack.push_back(Matrix4());
|
||||
@@ -1142,6 +1143,11 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
|
||||
}
|
||||
}
|
||||
|
||||
const Graphics::Capabilities &Graphics::getCapabilities() const
|
||||
{
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
Graphics::Stats Graphics::getStats() const
|
||||
{
|
||||
Stats stats;
|
||||
@@ -1451,8 +1457,6 @@ StringMap<Graphics::Feature, Graphics::FEATURE_MAX_ENUM>::Entry Graphics::featur
|
||||
{ "lighten", FEATURE_LIGHTEN },
|
||||
{ "fullnpot", FEATURE_FULL_NPOT },
|
||||
{ "pixelshaderhighp", FEATURE_PIXEL_SHADER_HIGHP },
|
||||
{ "arraytexture", FEATURE_ARRAY_TEXTURE },
|
||||
{ "volumetexture", FEATURE_VOLUME_TEXTURE },
|
||||
{ "glsl3", FEATURE_GLSL3 },
|
||||
{ "instancing", FEATURE_INSTANCING },
|
||||
};
|
||||
|
||||
@@ -159,8 +159,6 @@ public:
|
||||
FEATURE_LIGHTEN,
|
||||
FEATURE_FULL_NPOT,
|
||||
FEATURE_PIXEL_SHADER_HIGHP,
|
||||
FEATURE_ARRAY_TEXTURE,
|
||||
FEATURE_VOLUME_TEXTURE,
|
||||
FEATURE_GLSL3,
|
||||
FEATURE_INSTANCING,
|
||||
FEATURE_MAX_ENUM
|
||||
@@ -199,6 +197,13 @@ public:
|
||||
TEMPORARY_RT_STENCIL = (1 << 1),
|
||||
};
|
||||
|
||||
struct Capabilities
|
||||
{
|
||||
double limits[LIMIT_MAX_ENUM];
|
||||
bool features[FEATURE_MAX_ENUM];
|
||||
bool textureTypes[TEXTURE_MAX_ENUM];
|
||||
};
|
||||
|
||||
struct RendererInfo
|
||||
{
|
||||
std::string name;
|
||||
@@ -696,19 +701,10 @@ public:
|
||||
void polygon(DrawMode mode, const float *coords, size_t count);
|
||||
|
||||
/**
|
||||
* Gets whether a graphics feature is supported on this system.
|
||||
* Gets the graphics capabilities (feature support, limit values, and
|
||||
* supported texture types) of this system.
|
||||
**/
|
||||
virtual bool isSupported(Feature feature) const = 0;
|
||||
|
||||
/**
|
||||
* Gets whether the given texture type is supported on this system.
|
||||
**/
|
||||
virtual bool isTextureTypeSupported(TextureType textype) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the system-dependent numeric limit for the specified parameter.
|
||||
**/
|
||||
virtual double getSystemLimit(SystemLimit limittype) const = 0;
|
||||
const Capabilities &getCapabilities() const;
|
||||
|
||||
/**
|
||||
* Gets whether the specified pixel format is supported by Canvases or
|
||||
@@ -864,6 +860,7 @@ protected:
|
||||
|
||||
virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0;
|
||||
|
||||
virtual void initCapabilities() = 0;
|
||||
virtual void getAPIStats(int &drawcalls, int &shaderswitches) const = 0;
|
||||
|
||||
Canvas *getTemporaryCanvas(PixelFormat format, int w, int h, int samples);
|
||||
@@ -903,6 +900,8 @@ protected:
|
||||
|
||||
int canvasSwitchCount;
|
||||
|
||||
Capabilities capabilities;
|
||||
|
||||
static const size_t MAX_USER_STACK_DEPTH = 64;
|
||||
|
||||
private:
|
||||
|
||||
@@ -303,7 +303,7 @@ bool Mesh::isAttributeEnabled(const std::string &name) const
|
||||
void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step)
|
||||
{
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (step == STEP_PER_INSTANCE && !gfx->isSupported(Graphics::FEATURE_INSTANCING))
|
||||
if (step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING])
|
||||
throw love::Exception("Vertex attribute instancing is not supported on this system.");
|
||||
|
||||
if (mesh != this)
|
||||
|
||||
@@ -233,7 +233,7 @@ bool Shader::validate(Graphics *gfx, bool gles, const ShaderSource &source, bool
|
||||
return false;
|
||||
}
|
||||
|
||||
bool supportsGLSL3 = gfx->isSupported(Graphics::FEATURE_GLSL3);
|
||||
bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3];
|
||||
|
||||
int defaultversion = gles ? 100 : 120;
|
||||
EProfile defaultprofile = ENoProfile;
|
||||
|
||||
@@ -202,6 +202,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
gl.setupContext();
|
||||
|
||||
created = true;
|
||||
initCapabilities();
|
||||
|
||||
setViewportSize(width, height, pixelwidth, pixelheight);
|
||||
|
||||
@@ -272,7 +273,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
// We always need a default shader.
|
||||
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++)
|
||||
{
|
||||
if (i == Shader::STANDARD_ARRAY && !isSupported(FEATURE_ARRAY_TEXTURE))
|
||||
if (i == Shader::STANDARD_ARRAY && !capabilities.textureTypes[TEXTURE_2D_ARRAY])
|
||||
continue;
|
||||
|
||||
if (!Shader::standardShaders[i])
|
||||
@@ -1282,7 +1283,7 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
|
||||
|
||||
if (mode == BLEND_LIGHTEN || mode == BLEND_DARKEN)
|
||||
{
|
||||
if (!isSupported(FEATURE_LIGHTEN))
|
||||
if (!capabilities.features[FEATURE_LIGHTEN])
|
||||
throw love::Exception("The 'lighten' and 'darken' blend modes are not supported on this system.");
|
||||
}
|
||||
|
||||
@@ -1410,61 +1411,29 @@ void Graphics::getAPIStats(int &drawcalls, int &shaderswitches) const
|
||||
shaderswitches = gl.stats.shaderSwitches;
|
||||
}
|
||||
|
||||
double Graphics::getSystemLimit(SystemLimit limittype) const
|
||||
void Graphics::initCapabilities()
|
||||
{
|
||||
switch (limittype)
|
||||
{
|
||||
case LIMIT_POINT_SIZE:
|
||||
return (double) gl.getMaxPointSize();
|
||||
case LIMIT_TEXTURE_SIZE:
|
||||
return (double) gl.getMax2DTextureSize();
|
||||
case LIMIT_TEXTURE_LAYERS:
|
||||
return (double) gl.getMaxTextureLayers();
|
||||
case LIMIT_VOLUME_TEXTURE_SIZE:
|
||||
return (double) gl.getMax3DTextureSize();
|
||||
case LIMIT_CUBE_TEXTURE_SIZE:
|
||||
return (double) gl.getMaxCubeTextureSize();
|
||||
case LIMIT_MULTI_CANVAS:
|
||||
return (double) gl.getMaxRenderTargets();
|
||||
case LIMIT_CANVAS_MSAA:
|
||||
return (double) gl.getMaxRenderbufferSamples();
|
||||
case LIMIT_ANISOTROPY:
|
||||
return (double) gl.getMaxAnisotropy();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
capabilities.features[FEATURE_MULTI_CANVAS_FORMATS] = Canvas::isMultiFormatMultiCanvasSupported();
|
||||
capabilities.features[FEATURE_CLAMP_ZERO] = gl.isClampZeroTextureWrapSupported();
|
||||
capabilities.features[FEATURE_LIGHTEN] = GLAD_VERSION_1_4 || GLAD_ES_VERSION_3_0 || GLAD_EXT_blend_minmax;
|
||||
capabilities.features[FEATURE_FULL_NPOT] = GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot;
|
||||
capabilities.features[FEATURE_PIXEL_SHADER_HIGHP] = gl.isPixelShaderHighpSupported();
|
||||
capabilities.features[FEATURE_GLSL3] = GLAD_ES_VERSION_3_0 || gl.isCoreProfile();
|
||||
capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported();
|
||||
static_assert(FEATURE_MAX_ENUM == 7, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
|
||||
|
||||
bool Graphics::isSupported(Feature feature) const
|
||||
{
|
||||
switch (feature)
|
||||
{
|
||||
case FEATURE_MULTI_CANVAS_FORMATS:
|
||||
return Canvas::isMultiFormatMultiCanvasSupported();
|
||||
case FEATURE_CLAMP_ZERO:
|
||||
return gl.isClampZeroTextureWrapSupported();
|
||||
case FEATURE_LIGHTEN:
|
||||
return GLAD_VERSION_1_4 || GLAD_ES_VERSION_3_0 || GLAD_EXT_blend_minmax;
|
||||
case FEATURE_FULL_NPOT:
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot;
|
||||
case FEATURE_PIXEL_SHADER_HIGHP:
|
||||
return gl.isPixelShaderHighpSupported();
|
||||
case FEATURE_ARRAY_TEXTURE:
|
||||
return gl.isTextureTypeSupported(TEXTURE_2D_ARRAY);
|
||||
case FEATURE_VOLUME_TEXTURE:
|
||||
return gl.isTextureTypeSupported(TEXTURE_VOLUME);
|
||||
case FEATURE_GLSL3:
|
||||
return GLAD_ES_VERSION_3_0 || gl.isCoreProfile();
|
||||
case FEATURE_INSTANCING:
|
||||
return gl.isInstancingSupported();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize();
|
||||
capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize();
|
||||
capabilities.limits[LIMIT_TEXTURE_LAYERS] = gl.getMaxTextureLayers();
|
||||
capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = gl.getMax3DTextureSize();
|
||||
capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = gl.getMaxCubeTextureSize();
|
||||
capabilities.limits[LIMIT_MULTI_CANVAS] = gl.getMaxRenderTargets();
|
||||
capabilities.limits[LIMIT_CANVAS_MSAA] = gl.getMaxRenderbufferSamples();
|
||||
capabilities.limits[LIMIT_ANISOTROPY] = gl.getMaxAnisotropy();
|
||||
static_assert(LIMIT_MAX_ENUM == 8, "Graphics::initCapabilities must be updated when adding a new system limit!");
|
||||
|
||||
bool Graphics::isTextureTypeSupported(TextureType textype) const
|
||||
{
|
||||
return gl.isTextureTypeSupported(textype);
|
||||
for (int i = 0; i < TEXTURE_MAX_ENUM; i++)
|
||||
capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i);
|
||||
}
|
||||
|
||||
bool Graphics::isCanvasFormatSupported(PixelFormat format) const
|
||||
|
||||
@@ -117,9 +117,6 @@ public:
|
||||
|
||||
void setWireframe(bool enable) override;
|
||||
|
||||
bool isSupported(Feature feature) const override;
|
||||
bool isTextureTypeSupported(TextureType textype) const override;
|
||||
double getSystemLimit(SystemLimit limittype) const override;
|
||||
bool isCanvasFormatSupported(PixelFormat format) const override;
|
||||
bool isCanvasFormatSupported(PixelFormat format, bool readable) const override;
|
||||
bool isImageFormatSupported(PixelFormat format) const override;
|
||||
@@ -131,6 +128,7 @@ public:
|
||||
private:
|
||||
|
||||
love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override;
|
||||
void initCapabilities() override;
|
||||
void getAPIStats(int &drawcalls, int &shaderswitches) const override;
|
||||
|
||||
void endPass();
|
||||
|
||||
@@ -1926,6 +1926,7 @@ int w_setDefaultShaderCode(lua_State *L)
|
||||
|
||||
int w_getSupported(lua_State *L)
|
||||
{
|
||||
const Graphics::Capabilities &caps = instance()->getCapabilities();
|
||||
lua_createtable(L, 0, (int) Graphics::FEATURE_MAX_ENUM);
|
||||
|
||||
for (int i = 0; i < (int) Graphics::FEATURE_MAX_ENUM; i++)
|
||||
@@ -1936,7 +1937,7 @@ int w_getSupported(lua_State *L)
|
||||
if (!Graphics::getConstant(feature, name))
|
||||
continue;
|
||||
|
||||
luax_pushboolean(L, instance()->isSupported(feature));
|
||||
luax_pushboolean(L, caps.features[i]);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
@@ -2011,6 +2012,26 @@ int w_getImageFormats(lua_State *L)
|
||||
return w__getFormats(L, supported, ignore);
|
||||
}
|
||||
|
||||
int w_getTextureTypes(lua_State *L)
|
||||
{
|
||||
const Graphics::Capabilities &caps = instance()->getCapabilities();
|
||||
lua_createtable(L, 0, (int) TEXTURE_MAX_ENUM);
|
||||
|
||||
for (int i = 0; i < (int) TEXTURE_MAX_ENUM; i++)
|
||||
{
|
||||
TextureType textype = (TextureType) i;
|
||||
const char *name = nullptr;
|
||||
|
||||
if (!Texture::getConstant(textype, name))
|
||||
continue;
|
||||
|
||||
lua_pushnumber(L, caps.textureTypes[i]);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getRendererInfo(lua_State *L)
|
||||
{
|
||||
Graphics::RendererInfo info;
|
||||
@@ -2025,6 +2046,7 @@ int w_getRendererInfo(lua_State *L)
|
||||
|
||||
int w_getSystemLimits(lua_State *L)
|
||||
{
|
||||
const Graphics::Capabilities &caps = instance()->getCapabilities();
|
||||
lua_createtable(L, 0, (int) Graphics::LIMIT_MAX_ENUM);
|
||||
|
||||
for (int i = 0; i < (int) Graphics::LIMIT_MAX_ENUM; i++)
|
||||
@@ -2035,7 +2057,7 @@ int w_getSystemLimits(lua_State *L)
|
||||
if (!Graphics::getConstant(limittype, name))
|
||||
continue;
|
||||
|
||||
lua_pushnumber(L, instance()->getSystemLimit(limittype));
|
||||
lua_pushnumber(L, caps.limits[i]);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
@@ -2685,6 +2707,7 @@ static const luaL_Reg functions[] =
|
||||
{ "getImageFormats", w_getImageFormats },
|
||||
{ "getRendererInfo", w_getRendererInfo },
|
||||
{ "getSystemLimits", w_getSystemLimits },
|
||||
{ "getTextureTypes", w_getTextureTypes },
|
||||
{ "getStats", w_getStats },
|
||||
|
||||
{ "captureScreenshot", w_captureScreenshot },
|
||||
|
||||
Reference in New Issue
Block a user