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);
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:
+4 -1
View File
@@ -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);
+6 -2
View File
@@ -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 },
};
+13 -14
View File
@@ -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:
+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)
{
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)
+1 -1
View File
@@ -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;
+23 -54
View File
@@ -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
+1 -3
View File
@@ -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();
+25 -2
View File
@@ -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 },