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:
Alex Szpakowski
2017-06-27 22:26:30 -03:00
parent 5941982422
commit 54a049e206
9 changed files with 81 additions and 84 deletions
+7 -6
View File
@@ -72,6 +72,7 @@ Canvas::Canvas(const Settings &settings)
} }
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS); auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
const Graphics::Capabilities &caps = gfx->getCapabilities();
if (!gfx->isCanvasFormatSupported(format, readable)) if (!gfx->isCanvasFormatSupported(format, readable))
{ {
@@ -89,7 +90,7 @@ Canvas::Canvas(const Settings &settings)
if (!readable && texType != TEXTURE_2D) if (!readable && texType != TEXTURE_2D)
throw love::Exception("Non-readable pixel formats are only supported for 2D texture types."); 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"; const char *textypestr = "unknown";
Texture::getConstant(texType, textypestr); Texture::getConstant(texType, textypestr);
@@ -100,14 +101,14 @@ Canvas::Canvas(const Settings &settings)
switch (texType) switch (texType)
{ {
case TEXTURE_2D: case TEXTURE_2D:
maxsize = gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE); maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
if (pixelWidth > maxsize) if (pixelWidth > maxsize)
throw TextureTooLargeException("width", pixelWidth); throw TextureTooLargeException("width", pixelWidth);
else if (pixelHeight > maxsize) else if (pixelHeight > maxsize)
throw TextureTooLargeException("height", pixelHeight); throw TextureTooLargeException("height", pixelHeight);
break; break;
case TEXTURE_VOLUME: case TEXTURE_VOLUME:
maxsize = gfx->getSystemLimit(Graphics::LIMIT_VOLUME_TEXTURE_SIZE); maxsize = (int) caps.limits[Graphics::LIMIT_VOLUME_TEXTURE_SIZE];
if (pixelWidth > maxsize) if (pixelWidth > maxsize)
throw TextureTooLargeException("width", pixelWidth); throw TextureTooLargeException("width", pixelWidth);
else if (pixelHeight > maxsize) else if (pixelHeight > maxsize)
@@ -116,18 +117,18 @@ Canvas::Canvas(const Settings &settings)
throw TextureTooLargeException("depth", depth); throw TextureTooLargeException("depth", depth);
break; break;
case TEXTURE_2D_ARRAY: case TEXTURE_2D_ARRAY:
maxsize = gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE); maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
if (pixelWidth > maxsize) if (pixelWidth > maxsize)
throw TextureTooLargeException("width", pixelWidth); throw TextureTooLargeException("width", pixelWidth);
else if (pixelHeight > maxsize) else if (pixelHeight > maxsize)
throw TextureTooLargeException("height", pixelHeight); 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); throw TextureTooLargeException("array layer count", layers);
break; break;
case TEXTURE_CUBE: case TEXTURE_CUBE:
if (pixelWidth != pixelHeight) if (pixelWidth != pixelHeight)
throw love::Exception("Cubemap textures must have equal width and height."); 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); throw TextureTooLargeException("width", pixelWidth);
break; break;
default: default:
+4 -1
View File
@@ -99,7 +99,10 @@ Font::TextureSize Font::getNextTextureSize() const
int maxsize = 2048; int maxsize = 2048;
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS); auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
if (gfx != nullptr) 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 maxwidth = std::min(8192, maxsize);
int maxheight = std::min(4096, maxsize); int maxheight = std::min(4096, maxsize);
+6 -2
View File
@@ -112,6 +112,7 @@ Graphics::Graphics()
, streamBufferState() , streamBufferState()
, projectionMatrix() , projectionMatrix()
, canvasSwitchCount(0) , canvasSwitchCount(0)
, capabilities()
{ {
transformStack.reserve(16); transformStack.reserve(16);
transformStack.push_back(Matrix4()); 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 Graphics::Stats Graphics::getStats() const
{ {
Stats stats; Stats stats;
@@ -1451,8 +1457,6 @@ StringMap<Graphics::Feature, Graphics::FEATURE_MAX_ENUM>::Entry Graphics::featur
{ "lighten", FEATURE_LIGHTEN }, { "lighten", FEATURE_LIGHTEN },
{ "fullnpot", FEATURE_FULL_NPOT }, { "fullnpot", FEATURE_FULL_NPOT },
{ "pixelshaderhighp", FEATURE_PIXEL_SHADER_HIGHP }, { "pixelshaderhighp", FEATURE_PIXEL_SHADER_HIGHP },
{ "arraytexture", FEATURE_ARRAY_TEXTURE },
{ "volumetexture", FEATURE_VOLUME_TEXTURE },
{ "glsl3", FEATURE_GLSL3 }, { "glsl3", FEATURE_GLSL3 },
{ "instancing", FEATURE_INSTANCING }, { "instancing", FEATURE_INSTANCING },
}; };
+13 -14
View File
@@ -159,8 +159,6 @@ public:
FEATURE_LIGHTEN, FEATURE_LIGHTEN,
FEATURE_FULL_NPOT, FEATURE_FULL_NPOT,
FEATURE_PIXEL_SHADER_HIGHP, FEATURE_PIXEL_SHADER_HIGHP,
FEATURE_ARRAY_TEXTURE,
FEATURE_VOLUME_TEXTURE,
FEATURE_GLSL3, FEATURE_GLSL3,
FEATURE_INSTANCING, FEATURE_INSTANCING,
FEATURE_MAX_ENUM FEATURE_MAX_ENUM
@@ -199,6 +197,13 @@ public:
TEMPORARY_RT_STENCIL = (1 << 1), TEMPORARY_RT_STENCIL = (1 << 1),
}; };
struct Capabilities
{
double limits[LIMIT_MAX_ENUM];
bool features[FEATURE_MAX_ENUM];
bool textureTypes[TEXTURE_MAX_ENUM];
};
struct RendererInfo struct RendererInfo
{ {
std::string name; std::string name;
@@ -696,19 +701,10 @@ public:
void polygon(DrawMode mode, const float *coords, size_t count); 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; const Capabilities &getCapabilities() const;
/**
* 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;
/** /**
* Gets whether the specified pixel format is supported by Canvases or * 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 StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0;
virtual void initCapabilities() = 0;
virtual void getAPIStats(int &drawcalls, int &shaderswitches) const = 0; virtual void getAPIStats(int &drawcalls, int &shaderswitches) const = 0;
Canvas *getTemporaryCanvas(PixelFormat format, int w, int h, int samples); Canvas *getTemporaryCanvas(PixelFormat format, int w, int h, int samples);
@@ -903,6 +900,8 @@ protected:
int canvasSwitchCount; int canvasSwitchCount;
Capabilities capabilities;
static const size_t MAX_USER_STACK_DEPTH = 64; static const size_t MAX_USER_STACK_DEPTH = 64;
private: private:
+1 -1
View File
@@ -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) void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step)
{ {
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS); 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."); throw love::Exception("Vertex attribute instancing is not supported on this system.");
if (mesh != this) if (mesh != this)
+1 -1
View File
@@ -233,7 +233,7 @@ bool Shader::validate(Graphics *gfx, bool gles, const ShaderSource &source, bool
return false; return false;
} }
bool supportsGLSL3 = gfx->isSupported(Graphics::FEATURE_GLSL3); bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3];
int defaultversion = gles ? 100 : 120; int defaultversion = gles ? 100 : 120;
EProfile defaultprofile = ENoProfile; EProfile defaultprofile = ENoProfile;
+23 -54
View File
@@ -202,6 +202,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
gl.setupContext(); gl.setupContext();
created = true; created = true;
initCapabilities();
setViewportSize(width, height, pixelwidth, pixelheight); 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. // We always need a default shader.
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) 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; continue;
if (!Shader::standardShaders[i]) if (!Shader::standardShaders[i])
@@ -1282,7 +1283,7 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
if (mode == BLEND_LIGHTEN || mode == BLEND_DARKEN) 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."); 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; shaderswitches = gl.stats.shaderSwitches;
} }
double Graphics::getSystemLimit(SystemLimit limittype) const void Graphics::initCapabilities()
{ {
switch (limittype) capabilities.features[FEATURE_MULTI_CANVAS_FORMATS] = Canvas::isMultiFormatMultiCanvasSupported();
{ capabilities.features[FEATURE_CLAMP_ZERO] = gl.isClampZeroTextureWrapSupported();
case LIMIT_POINT_SIZE: capabilities.features[FEATURE_LIGHTEN] = GLAD_VERSION_1_4 || GLAD_ES_VERSION_3_0 || GLAD_EXT_blend_minmax;
return (double) gl.getMaxPointSize(); capabilities.features[FEATURE_FULL_NPOT] = GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot;
case LIMIT_TEXTURE_SIZE: capabilities.features[FEATURE_PIXEL_SHADER_HIGHP] = gl.isPixelShaderHighpSupported();
return (double) gl.getMax2DTextureSize(); capabilities.features[FEATURE_GLSL3] = GLAD_ES_VERSION_3_0 || gl.isCoreProfile();
case LIMIT_TEXTURE_LAYERS: capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported();
return (double) gl.getMaxTextureLayers(); static_assert(FEATURE_MAX_ENUM == 7, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
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;
}
}
bool Graphics::isSupported(Feature feature) const capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize();
{ capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize();
switch (feature) capabilities.limits[LIMIT_TEXTURE_LAYERS] = gl.getMaxTextureLayers();
{ capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = gl.getMax3DTextureSize();
case FEATURE_MULTI_CANVAS_FORMATS: capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = gl.getMaxCubeTextureSize();
return Canvas::isMultiFormatMultiCanvasSupported(); capabilities.limits[LIMIT_MULTI_CANVAS] = gl.getMaxRenderTargets();
case FEATURE_CLAMP_ZERO: capabilities.limits[LIMIT_CANVAS_MSAA] = gl.getMaxRenderbufferSamples();
return gl.isClampZeroTextureWrapSupported(); capabilities.limits[LIMIT_ANISOTROPY] = gl.getMaxAnisotropy();
case FEATURE_LIGHTEN: static_assert(LIMIT_MAX_ENUM == 8, "Graphics::initCapabilities must be updated when adding a new system limit!");
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;
}
}
bool Graphics::isTextureTypeSupported(TextureType textype) const for (int i = 0; i < TEXTURE_MAX_ENUM; i++)
{ capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i);
return gl.isTextureTypeSupported(textype);
} }
bool Graphics::isCanvasFormatSupported(PixelFormat format) const bool Graphics::isCanvasFormatSupported(PixelFormat format) const
+1 -3
View File
@@ -117,9 +117,6 @@ public:
void setWireframe(bool enable) override; 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) const override;
bool isCanvasFormatSupported(PixelFormat format, bool readable) const override; bool isCanvasFormatSupported(PixelFormat format, bool readable) const override;
bool isImageFormatSupported(PixelFormat format) const override; bool isImageFormatSupported(PixelFormat format) const override;
@@ -131,6 +128,7 @@ public:
private: private:
love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override; love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override;
void initCapabilities() override;
void getAPIStats(int &drawcalls, int &shaderswitches) const override; void getAPIStats(int &drawcalls, int &shaderswitches) const override;
void endPass(); void endPass();
+25 -2
View File
@@ -1926,6 +1926,7 @@ int w_setDefaultShaderCode(lua_State *L)
int w_getSupported(lua_State *L) int w_getSupported(lua_State *L)
{ {
const Graphics::Capabilities &caps = instance()->getCapabilities();
lua_createtable(L, 0, (int) Graphics::FEATURE_MAX_ENUM); lua_createtable(L, 0, (int) Graphics::FEATURE_MAX_ENUM);
for (int i = 0; i < (int) Graphics::FEATURE_MAX_ENUM; i++) 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)) if (!Graphics::getConstant(feature, name))
continue; continue;
luax_pushboolean(L, instance()->isSupported(feature)); luax_pushboolean(L, caps.features[i]);
lua_setfield(L, -2, name); lua_setfield(L, -2, name);
} }
@@ -2011,6 +2012,26 @@ int w_getImageFormats(lua_State *L)
return w__getFormats(L, supported, ignore); 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) int w_getRendererInfo(lua_State *L)
{ {
Graphics::RendererInfo info; Graphics::RendererInfo info;
@@ -2025,6 +2046,7 @@ int w_getRendererInfo(lua_State *L)
int w_getSystemLimits(lua_State *L) int w_getSystemLimits(lua_State *L)
{ {
const Graphics::Capabilities &caps = instance()->getCapabilities();
lua_createtable(L, 0, (int) Graphics::LIMIT_MAX_ENUM); lua_createtable(L, 0, (int) Graphics::LIMIT_MAX_ENUM);
for (int i = 0; i < (int) Graphics::LIMIT_MAX_ENUM; i++) 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)) if (!Graphics::getConstant(limittype, name))
continue; continue;
lua_pushnumber(L, instance()->getSystemLimit(limittype)); lua_pushnumber(L, caps.limits[i]);
lua_setfield(L, -2, name); lua_setfield(L, -2, name);
} }
@@ -2685,6 +2707,7 @@ static const luaL_Reg functions[] =
{ "getImageFormats", w_getImageFormats }, { "getImageFormats", w_getImageFormats },
{ "getRendererInfo", w_getRendererInfo }, { "getRendererInfo", w_getRendererInfo },
{ "getSystemLimits", w_getSystemLimits }, { "getSystemLimits", w_getSystemLimits },
{ "getTextureTypes", w_getTextureTypes },
{ "getStats", w_getStats }, { "getStats", w_getStats },
{ "captureScreenshot", w_captureScreenshot }, { "captureScreenshot", w_captureScreenshot },