mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Refactor sampler state parameters for textures.
This commit is contained in:
@@ -64,10 +64,7 @@ Canvas::Canvas(const Settings &settings)
|
||||
throw love::Exception("Non-readable and MSAA textures cannot have mipmaps.");
|
||||
|
||||
if (settings.mipmaps != MIPMAPS_NONE)
|
||||
{
|
||||
mipmapCount = getTotalMipmapCount(pixelWidth, pixelHeight, depth);
|
||||
filter.mipmap = defaultMipmapFilter;
|
||||
}
|
||||
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
const Graphics::Capabilities &caps = gfx->getCapabilities();
|
||||
|
||||
@@ -47,18 +47,20 @@ int Font::fontCount = 0;
|
||||
|
||||
const vertex::CommonFormat Font::vertexFormat = vertex::CommonFormat::XYf_STus_RGBAub;
|
||||
|
||||
Font::Font(love::font::Rasterizer *r, const Texture::Filter &f)
|
||||
Font::Font(love::font::Rasterizer *r, const SamplerState &s)
|
||||
: rasterizers({r})
|
||||
, height(r->getHeight())
|
||||
, lineHeight(1)
|
||||
, textureWidth(128)
|
||||
, textureHeight(128)
|
||||
, filter(f)
|
||||
, samplerState()
|
||||
, dpiScale(r->getDPIScale())
|
||||
, useSpacesAsTab(false)
|
||||
, textureCacheID(0)
|
||||
{
|
||||
filter.mipmap = Texture::FILTER_NONE;
|
||||
samplerState.minFilter = s.minFilter;
|
||||
samplerState.magFilter = s.magFilter;
|
||||
samplerState.maxAnisotropy = s.maxAnisotropy;
|
||||
|
||||
// Try to find the best texture size match for the font size. default to the
|
||||
// largest texture size if no rough match is found.
|
||||
@@ -150,7 +152,7 @@ void Font::createTexture()
|
||||
|
||||
Image::Settings settings;
|
||||
image = gfx->newImage(TEXTURE_2D, pixelFormat, size.width, size.height, 1, settings);
|
||||
image->setFilter(filter);
|
||||
image->setSamplerState(samplerState);
|
||||
|
||||
{
|
||||
size_t bpp = getPixelFormatSize(pixelFormat);
|
||||
@@ -918,17 +920,19 @@ float Font::getLineHeight() const
|
||||
return lineHeight;
|
||||
}
|
||||
|
||||
void Font::setFilter(const Texture::Filter &f)
|
||||
void Font::setSamplerState(const SamplerState &s)
|
||||
{
|
||||
for (const auto &image : images)
|
||||
image->setFilter(f);
|
||||
samplerState.minFilter = s.minFilter;
|
||||
samplerState.magFilter = s.magFilter;
|
||||
samplerState.maxAnisotropy = s.maxAnisotropy;
|
||||
|
||||
filter = f;
|
||||
for (const auto &image : images)
|
||||
image->setSamplerState(samplerState);
|
||||
}
|
||||
|
||||
const Texture::Filter &Font::getFilter() const
|
||||
const SamplerState &Font::getSamplerState() const
|
||||
{
|
||||
return filter;
|
||||
return samplerState;
|
||||
}
|
||||
|
||||
int Font::getAscent() const
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
int vertexcount;
|
||||
};
|
||||
|
||||
Font(love::font::Rasterizer *r, const Texture::Filter &filter);
|
||||
Font(love::font::Rasterizer *r, const SamplerState &samplerState);
|
||||
|
||||
virtual ~Font();
|
||||
|
||||
@@ -158,8 +158,8 @@ public:
|
||||
**/
|
||||
float getLineHeight() const;
|
||||
|
||||
void setFilter(const Texture::Filter &f);
|
||||
const Texture::Filter &getFilter() const;
|
||||
void setSamplerState(const SamplerState &s);
|
||||
const SamplerState &getSamplerState() const;
|
||||
|
||||
// Extra font metrics
|
||||
int getAscent() const;
|
||||
@@ -227,7 +227,7 @@ private:
|
||||
|
||||
PixelFormat pixelFormat;
|
||||
|
||||
Texture::Filter filter;
|
||||
SamplerState samplerState;
|
||||
|
||||
float dpiScale;
|
||||
|
||||
|
||||
@@ -184,19 +184,19 @@ Quad *Graphics::newQuad(Quad::Viewport v, double sw, double sh)
|
||||
return new Quad(v, sw, sh);
|
||||
}
|
||||
|
||||
Font *Graphics::newFont(love::font::Rasterizer *data, const Texture::Filter &filter)
|
||||
Font *Graphics::newFont(love::font::Rasterizer *data)
|
||||
{
|
||||
return new Font(data, filter);
|
||||
return new Font(data, states.back().defaultSamplerState);
|
||||
}
|
||||
|
||||
Font *Graphics::newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting, const Texture::Filter &filter)
|
||||
Font *Graphics::newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting)
|
||||
{
|
||||
auto fontmodule = Module::getInstance<font::Font>(M_FONT);
|
||||
if (!fontmodule)
|
||||
throw love::Exception("Font module has not been loaded.");
|
||||
|
||||
StrongRef<font::Rasterizer> r(fontmodule->newTrueTypeRasterizer(size, hinting), Acquire::NORETAIN);
|
||||
return newFont(r.get(), filter);
|
||||
return newFont(r.get());
|
||||
}
|
||||
|
||||
Video *Graphics::newVideo(love::video::VideoStream *stream, float dpiscale)
|
||||
@@ -402,8 +402,7 @@ void Graphics::restoreState(const DisplayState &s)
|
||||
setColorMask(s.colorMask);
|
||||
setWireframe(s.wireframe);
|
||||
|
||||
setDefaultFilter(s.defaultFilter);
|
||||
setDefaultMipmapFilter(s.defaultMipmapFilter, s.defaultMipmapSharpness);
|
||||
setDefaultSamplerState(s.defaultSamplerState);
|
||||
}
|
||||
|
||||
void Graphics::restoreStateChecked(const DisplayState &s)
|
||||
@@ -479,8 +478,7 @@ void Graphics::restoreStateChecked(const DisplayState &s)
|
||||
if (s.wireframe != cur.wireframe)
|
||||
setWireframe(s.wireframe);
|
||||
|
||||
setDefaultFilter(s.defaultFilter);
|
||||
setDefaultMipmapFilter(s.defaultMipmapFilter, s.defaultMipmapSharpness);
|
||||
setDefaultSamplerState(s.defaultSamplerState);
|
||||
}
|
||||
|
||||
Colorf Graphics::getColor() const
|
||||
@@ -923,30 +921,14 @@ const BlendState &Graphics::getBlendState() const
|
||||
return states.back().blend;
|
||||
}
|
||||
|
||||
void Graphics::setDefaultFilter(const Texture::Filter &f)
|
||||
void Graphics::setDefaultSamplerState(const SamplerState &s)
|
||||
{
|
||||
Texture::defaultFilter = f;
|
||||
states.back().defaultFilter = f;
|
||||
states.back().defaultSamplerState = s;
|
||||
}
|
||||
|
||||
const Texture::Filter &Graphics::getDefaultFilter() const
|
||||
const SamplerState &Graphics::getDefaultSamplerState() const
|
||||
{
|
||||
return Texture::defaultFilter;
|
||||
}
|
||||
|
||||
void Graphics::setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness)
|
||||
{
|
||||
Texture::defaultMipmapFilter = filter;
|
||||
Texture::defaultMipmapSharpness = sharpness;
|
||||
|
||||
states.back().defaultMipmapFilter = filter;
|
||||
states.back().defaultMipmapSharpness = sharpness;
|
||||
}
|
||||
|
||||
void Graphics::getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const
|
||||
{
|
||||
*filter = Texture::defaultMipmapFilter;
|
||||
*sharpness = Texture::defaultMipmapSharpness;
|
||||
return states.back().defaultSamplerState;
|
||||
}
|
||||
|
||||
void Graphics::setLineWidth(float width)
|
||||
|
||||
@@ -433,8 +433,8 @@ public:
|
||||
virtual Image *newImage(TextureType textype, PixelFormat format, int width, int height, int slices, const Image::Settings &settings) = 0;
|
||||
|
||||
Quad *newQuad(Quad::Viewport v, double sw, double sh);
|
||||
Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter);
|
||||
Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting, const Texture::Filter &filter = Texture::defaultFilter);
|
||||
Font *newFont(love::font::Rasterizer *data);
|
||||
Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting);
|
||||
Video *newVideo(love::video::VideoStream *stream, float dpiscale);
|
||||
|
||||
SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage);
|
||||
@@ -620,20 +620,14 @@ public:
|
||||
const BlendState &getBlendState() const;
|
||||
|
||||
/**
|
||||
* Sets the default filter for images, canvases, and fonts.
|
||||
* Sets the default sampler state for images, canvases, and fonts.
|
||||
**/
|
||||
void setDefaultFilter(const Texture::Filter &f);
|
||||
void setDefaultSamplerState(const SamplerState &s);
|
||||
|
||||
/**
|
||||
* Gets the default filter for images, canvases, and fonts.
|
||||
* Gets the default sampler state for images, canvases, and fonts.
|
||||
**/
|
||||
const Texture::Filter &getDefaultFilter() const;
|
||||
|
||||
/**
|
||||
* Default Image mipmap filter mode and sharpness values.
|
||||
**/
|
||||
void setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness);
|
||||
void getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const;
|
||||
const SamplerState &getDefaultSamplerState() const;
|
||||
|
||||
/**
|
||||
* Sets the line width.
|
||||
@@ -920,10 +914,7 @@ protected:
|
||||
|
||||
bool wireframe = false;
|
||||
|
||||
Texture::Filter defaultFilter = Texture::Filter();
|
||||
|
||||
Texture::FilterMode defaultMipmapFilter = Texture::FILTER_LINEAR;
|
||||
float defaultMipmapSharpness = 0.0f;
|
||||
SamplerState defaultSamplerState = SamplerState();
|
||||
};
|
||||
|
||||
struct StreamBufferState
|
||||
|
||||
@@ -103,9 +103,6 @@ void Image::init(PixelFormat fmt, int w, int h, const Settings &settings)
|
||||
|
||||
mipmapCount = mipmapsType == MIPMAPS_NONE ? 1 : getTotalMipmapCount(w, h, depth);
|
||||
|
||||
if (mipmapCount > 1)
|
||||
filter.mipmap = defaultMipmapFilter;
|
||||
|
||||
initQuad();
|
||||
|
||||
++imageCount;
|
||||
|
||||
@@ -125,7 +125,7 @@ void Shader::checkMainTexture(Texture *tex) const
|
||||
if (!tex->isReadable())
|
||||
throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
|
||||
|
||||
checkMainTextureType(tex->getTextureType(), tex->getDepthSampleMode().hasValue);
|
||||
checkMainTextureType(tex->getTextureType(), tex->getSamplerState().depthSampleMode.hasValue);
|
||||
}
|
||||
|
||||
bool Shader::validate(ShaderStage *vertex, ShaderStage *pixel, std::string &err)
|
||||
|
||||
+138
-106
@@ -33,11 +33,129 @@ namespace love
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
love::Type Texture::type("Texture", &Drawable::type);
|
||||
uint64 SamplerState::toKey() const
|
||||
{
|
||||
union { float f; uint32 i; } conv;
|
||||
conv.f = lodBias;
|
||||
|
||||
Texture::Filter Texture::defaultFilter;
|
||||
Texture::FilterMode Texture::defaultMipmapFilter = Texture::FILTER_LINEAR;
|
||||
float Texture::defaultMipmapSharpness = 0.0f;
|
||||
return (minFilter << 0) | (magFilter << 1) | (mipmapFilter << 2)
|
||||
| (wrapU << 4) | (wrapV << 7) | (wrapW << 10)
|
||||
| (maxAnisotropy << 12) | (minLod << 16) | (maxLod << 20)
|
||||
| (depthSampleMode.hasValue << 24) | (depthSampleMode.value << 25)
|
||||
| ((uint64)conv.i << 32);
|
||||
}
|
||||
|
||||
SamplerState SamplerState::fromKey(uint64 key)
|
||||
{
|
||||
const uint32 BITS_1 = 0x1;
|
||||
const uint32 BITS_2 = 0x3;
|
||||
const uint32 BITS_3 = 0x7;
|
||||
const uint32 BITS_4 = 0xF;
|
||||
|
||||
SamplerState s;
|
||||
|
||||
s.minFilter = (FilterMode) ((key >> 0) & BITS_1);
|
||||
s.magFilter = (FilterMode) ((key >> 1) & BITS_1);
|
||||
s.mipmapFilter = (MipmapFilterMode) ((key >> 2) & BITS_2);
|
||||
|
||||
s.wrapU = (WrapMode) ((key >> 4 ) & BITS_3);
|
||||
s.wrapV = (WrapMode) ((key >> 7 ) & BITS_3);
|
||||
s.wrapW = (WrapMode) ((key >> 10) & BITS_3);
|
||||
|
||||
s.maxAnisotropy = (key >> 12) & BITS_4;
|
||||
|
||||
s.minLod = (key >> 16) & BITS_4;
|
||||
s.maxLod = (key >> 20) & BITS_4;
|
||||
|
||||
s.depthSampleMode.hasValue = ((key >> 24) & BITS_1) != 0;
|
||||
s.depthSampleMode.value = (CompareMode) ((key >> 25) & BITS_4);
|
||||
|
||||
union { float f; uint32 i; } conv;
|
||||
conv.i = (uint32) (key >> 32);
|
||||
s.lodBias = conv.f;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool SamplerState::isClampZeroOrOne(WrapMode w)
|
||||
{
|
||||
return w == WRAP_CLAMP_ONE || w == WRAP_CLAMP_ZERO;
|
||||
}
|
||||
|
||||
static StringMap<SamplerState::FilterMode, SamplerState::FILTER_MAX_ENUM>::Entry filterModeEntries[] =
|
||||
{
|
||||
{ "linear", SamplerState::FILTER_LINEAR },
|
||||
{ "nearest", SamplerState::FILTER_NEAREST },
|
||||
};
|
||||
|
||||
static StringMap<SamplerState::FilterMode, SamplerState::FILTER_MAX_ENUM> filterModes(filterModeEntries, sizeof(filterModeEntries));
|
||||
|
||||
static StringMap<SamplerState::MipmapFilterMode, SamplerState::MIPMAP_FILTER_MAX_ENUM>::Entry mipmapFilterModeEntries[] =
|
||||
{
|
||||
{ "none", SamplerState::MIPMAP_FILTER_NONE },
|
||||
{ "linear", SamplerState::MIPMAP_FILTER_LINEAR },
|
||||
{ "nearest", SamplerState::MIPMAP_FILTER_NEAREST },
|
||||
};
|
||||
|
||||
static StringMap<SamplerState::MipmapFilterMode, SamplerState::MIPMAP_FILTER_MAX_ENUM> mipmapFilterModes(mipmapFilterModeEntries, sizeof(mipmapFilterModeEntries));
|
||||
|
||||
static StringMap<SamplerState::WrapMode, SamplerState::WRAP_MAX_ENUM>::Entry wrapModeEntries[] =
|
||||
{
|
||||
{ "clamp", SamplerState::WRAP_CLAMP },
|
||||
{ "clampzero", SamplerState::WRAP_CLAMP_ZERO },
|
||||
{ "clampone", SamplerState::WRAP_CLAMP_ONE },
|
||||
{ "repeat", SamplerState::WRAP_REPEAT },
|
||||
{ "mirroredrepeat", SamplerState::WRAP_MIRRORED_REPEAT },
|
||||
};
|
||||
|
||||
static StringMap<SamplerState::WrapMode, SamplerState::WRAP_MAX_ENUM> wrapModes(wrapModeEntries, sizeof(wrapModeEntries));
|
||||
|
||||
bool SamplerState::getConstant(const char *in, FilterMode &out)
|
||||
{
|
||||
return filterModes.find(in, out);
|
||||
}
|
||||
|
||||
bool SamplerState::getConstant(FilterMode in, const char *&out)
|
||||
{
|
||||
return filterModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> SamplerState::getConstants(FilterMode)
|
||||
{
|
||||
return filterModes.getNames();
|
||||
}
|
||||
|
||||
bool SamplerState::getConstant(const char *in, MipmapFilterMode &out)
|
||||
{
|
||||
return mipmapFilterModes.find(in, out);
|
||||
}
|
||||
|
||||
bool SamplerState::getConstant(MipmapFilterMode in, const char *&out)
|
||||
{
|
||||
return mipmapFilterModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> SamplerState::getConstants(MipmapFilterMode)
|
||||
{
|
||||
return mipmapFilterModes.getNames();
|
||||
}
|
||||
|
||||
bool SamplerState::getConstant(const char *in, WrapMode &out)
|
||||
{
|
||||
return wrapModes.find(in, out);
|
||||
}
|
||||
|
||||
bool SamplerState::getConstant(WrapMode in, const char *&out)
|
||||
{
|
||||
return wrapModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> SamplerState::getConstants(WrapMode)
|
||||
{
|
||||
return wrapModes.getNames();
|
||||
}
|
||||
|
||||
love::Type Texture::type("Texture", &Drawable::type);
|
||||
int64 Texture::totalGraphicsMemory = 0;
|
||||
|
||||
Texture::Texture(TextureType texType)
|
||||
@@ -51,11 +169,12 @@ Texture::Texture(TextureType texType)
|
||||
, mipmapCount(1)
|
||||
, pixelWidth(0)
|
||||
, pixelHeight(0)
|
||||
, filter(defaultFilter)
|
||||
, wrap()
|
||||
, mipmapSharpness(defaultMipmapSharpness)
|
||||
, samplerState()
|
||||
, graphicsMemorySize(0)
|
||||
{
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
samplerState = gfx->getDefaultSamplerState();
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
@@ -252,45 +371,25 @@ float Texture::getDPIScale() const
|
||||
return (float) pixelHeight / (float) height;
|
||||
}
|
||||
|
||||
void Texture::setFilter(const Filter &f)
|
||||
void Texture::setSamplerState(const SamplerState &s)
|
||||
{
|
||||
if (!validateFilter(f, getMipmapCount() > 1))
|
||||
{
|
||||
if (f.mipmap != FILTER_NONE && getMipmapCount() == 1)
|
||||
throw love::Exception("Non-mipmapped texture cannot have mipmap filtering.");
|
||||
else
|
||||
throw love::Exception("Invalid texture filter.");
|
||||
}
|
||||
if (s.depthSampleMode.hasValue && (!readable || !isPixelFormatDepthStencil(format)))
|
||||
throw love::Exception("Only readable depth textures can have a depth sample compare mode.");
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
filter = f;
|
||||
samplerState = s;
|
||||
|
||||
if (samplerState.mipmapFilter != SamplerState::MIPMAP_FILTER_NONE && getMipmapCount() == 1)
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
|
||||
if (texType == TEXTURE_CUBE)
|
||||
samplerState.wrapU = samplerState.wrapV = samplerState.wrapW = SamplerState::WRAP_CLAMP;
|
||||
}
|
||||
|
||||
const Texture::Filter &Texture::getFilter() const
|
||||
const SamplerState &Texture::getSamplerState() const
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
const Texture::Wrap &Texture::getWrap() const
|
||||
{
|
||||
return wrap;
|
||||
}
|
||||
|
||||
float Texture::getMipmapSharpness() const
|
||||
{
|
||||
return mipmapSharpness;
|
||||
}
|
||||
|
||||
void Texture::setDepthSampleMode(Optional<CompareMode> mode)
|
||||
{
|
||||
if (mode.hasValue && (!readable || !isPixelFormatDepthStencil(format)))
|
||||
throw love::Exception("Only readable depth textures can have a depth sample compare mode.");
|
||||
}
|
||||
|
||||
Optional<CompareMode> Texture::getDepthSampleMode() const
|
||||
{
|
||||
return depthCompareMode;
|
||||
return samplerState;
|
||||
}
|
||||
|
||||
Quad *Texture::getQuad() const
|
||||
@@ -298,23 +397,6 @@ Quad *Texture::getQuad() const
|
||||
return quad;
|
||||
}
|
||||
|
||||
bool Texture::validateFilter(const Filter &f, bool mipmapsAllowed)
|
||||
{
|
||||
if (!mipmapsAllowed && f.mipmap != FILTER_NONE)
|
||||
return false;
|
||||
|
||||
if (f.mag != FILTER_LINEAR && f.mag != FILTER_NEAREST)
|
||||
return false;
|
||||
|
||||
if (f.min != FILTER_LINEAR && f.min != FILTER_NEAREST)
|
||||
return false;
|
||||
|
||||
if (f.mipmap != FILTER_LINEAR && f.mipmap != FILTER_NEAREST && f.mipmap != FILTER_NONE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Texture::getTotalMipmapCount(int w, int h)
|
||||
{
|
||||
return (int) log2(std::max(w, h)) + 1;
|
||||
@@ -556,36 +638,6 @@ std::vector<std::string> Texture::getConstants(TextureType)
|
||||
return texTypes.getNames();
|
||||
}
|
||||
|
||||
bool Texture::getConstant(const char *in, FilterMode &out)
|
||||
{
|
||||
return filterModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Texture::getConstant(FilterMode in, const char *&out)
|
||||
{
|
||||
return filterModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> Texture::getConstants(FilterMode)
|
||||
{
|
||||
return filterModes.getNames();
|
||||
}
|
||||
|
||||
bool Texture::getConstant(const char *in, WrapMode &out)
|
||||
{
|
||||
return wrapModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Texture::getConstant(WrapMode in, const char *&out)
|
||||
{
|
||||
return wrapModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> Texture::getConstants(WrapMode)
|
||||
{
|
||||
return wrapModes.getNames();
|
||||
}
|
||||
|
||||
StringMap<TextureType, TEXTURE_MAX_ENUM>::Entry Texture::texTypeEntries[] =
|
||||
{
|
||||
{ "2d", TEXTURE_2D },
|
||||
@@ -596,25 +648,5 @@ StringMap<TextureType, TEXTURE_MAX_ENUM>::Entry Texture::texTypeEntries[] =
|
||||
|
||||
StringMap<TextureType, TEXTURE_MAX_ENUM> Texture::texTypes(Texture::texTypeEntries, sizeof(Texture::texTypeEntries));
|
||||
|
||||
StringMap<Texture::FilterMode, Texture::FILTER_MAX_ENUM>::Entry Texture::filterModeEntries[] =
|
||||
{
|
||||
{ "linear", FILTER_LINEAR },
|
||||
{ "nearest", FILTER_NEAREST },
|
||||
{ "none", FILTER_NONE },
|
||||
};
|
||||
|
||||
StringMap<Texture::FilterMode, Texture::FILTER_MAX_ENUM> Texture::filterModes(Texture::filterModeEntries, sizeof(Texture::filterModeEntries));
|
||||
|
||||
StringMap<Texture::WrapMode, Texture::WRAP_MAX_ENUM>::Entry Texture::wrapModeEntries[] =
|
||||
{
|
||||
{ "clamp", WRAP_CLAMP },
|
||||
{ "clampzero", WRAP_CLAMP_ZERO },
|
||||
{ "clampone", WRAP_CLAMP_ONE },
|
||||
{ "repeat", WRAP_REPEAT },
|
||||
{ "mirroredrepeat", WRAP_MIRRORED_REPEAT },
|
||||
};
|
||||
|
||||
StringMap<Texture::WrapMode, Texture::WRAP_MAX_ENUM> Texture::wrapModes(Texture::wrapModeEntries, sizeof(Texture::wrapModeEntries));
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -55,16 +55,8 @@ enum TextureType
|
||||
TEXTURE_MAX_ENUM
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for 2D textures. All textures can be drawn with Quads, have a
|
||||
* width and height, and have filter and wrap modes.
|
||||
**/
|
||||
class Texture : public Drawable, public Resource
|
||||
struct SamplerState
|
||||
{
|
||||
public:
|
||||
|
||||
static love::Type type;
|
||||
|
||||
enum WrapMode
|
||||
{
|
||||
WRAP_CLAMP,
|
||||
@@ -77,26 +69,63 @@ public:
|
||||
|
||||
enum FilterMode
|
||||
{
|
||||
FILTER_NONE,
|
||||
FILTER_LINEAR,
|
||||
FILTER_NEAREST,
|
||||
FILTER_MAX_ENUM
|
||||
};
|
||||
|
||||
struct Filter
|
||||
enum MipmapFilterMode
|
||||
{
|
||||
FilterMode min = FILTER_LINEAR;
|
||||
FilterMode mag = FILTER_LINEAR;
|
||||
FilterMode mipmap = FILTER_NONE;
|
||||
float anisotropy = 1.0f;
|
||||
MIPMAP_FILTER_NONE,
|
||||
MIPMAP_FILTER_LINEAR,
|
||||
MIPMAP_FILTER_NEAREST,
|
||||
MIPMAP_FILTER_MAX_ENUM
|
||||
};
|
||||
|
||||
struct Wrap
|
||||
{
|
||||
WrapMode s = WRAP_CLAMP;
|
||||
WrapMode t = WRAP_CLAMP;
|
||||
WrapMode r = WRAP_CLAMP;
|
||||
};
|
||||
FilterMode minFilter = FILTER_LINEAR;
|
||||
FilterMode magFilter = FILTER_LINEAR;
|
||||
MipmapFilterMode mipmapFilter = MIPMAP_FILTER_NONE;
|
||||
|
||||
WrapMode wrapU = WRAP_CLAMP;
|
||||
WrapMode wrapV = WRAP_CLAMP;
|
||||
WrapMode wrapW = WRAP_CLAMP;
|
||||
|
||||
float lodBias = 0.0f;
|
||||
|
||||
uint8 maxAnisotropy = 1;
|
||||
|
||||
uint8 minLod = 0;
|
||||
uint8 maxLod = LOVE_UINT8_MAX;
|
||||
|
||||
Optional<CompareMode> depthSampleMode;
|
||||
|
||||
uint64 toKey() const;
|
||||
static SamplerState fromKey(uint64 key);
|
||||
|
||||
static bool isClampZeroOrOne(WrapMode w);
|
||||
|
||||
static bool getConstant(const char *in, FilterMode &out);
|
||||
static bool getConstant(FilterMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(FilterMode);
|
||||
|
||||
static bool getConstant(const char *in, MipmapFilterMode &out);
|
||||
static bool getConstant(MipmapFilterMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(MipmapFilterMode);
|
||||
|
||||
static bool getConstant(const char *in, WrapMode &out);
|
||||
static bool getConstant(WrapMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(WrapMode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for 2D textures. All textures can be drawn with Quads, have a
|
||||
* width and height, and have filter and wrap modes.
|
||||
**/
|
||||
class Texture : public Drawable, public Resource
|
||||
{
|
||||
public:
|
||||
|
||||
static love::Type type;
|
||||
|
||||
enum MipmapsType
|
||||
{
|
||||
@@ -135,10 +164,6 @@ public:
|
||||
|
||||
}; // Slices
|
||||
|
||||
static Filter defaultFilter;
|
||||
static FilterMode defaultMipmapFilter;
|
||||
static float defaultMipmapSharpness;
|
||||
|
||||
static int64 totalGraphicsMemory;
|
||||
|
||||
Texture(TextureType texType);
|
||||
@@ -173,40 +198,18 @@ public:
|
||||
|
||||
float getDPIScale() const;
|
||||
|
||||
virtual void setFilter(const Filter &f);
|
||||
virtual const Filter &getFilter() const;
|
||||
|
||||
virtual bool setWrap(const Wrap &w) = 0;
|
||||
virtual const Wrap &getWrap() const;
|
||||
|
||||
// Sets the mipmap texture LOD bias (sharpness) value.
|
||||
virtual bool setMipmapSharpness(float sharpness) = 0;
|
||||
float getMipmapSharpness() const;
|
||||
|
||||
virtual void setDepthSampleMode(Optional<CompareMode> mode = Optional<CompareMode>());
|
||||
Optional<CompareMode> getDepthSampleMode() const;
|
||||
virtual void setSamplerState(const SamplerState &s);
|
||||
const SamplerState &getSamplerState() const;
|
||||
|
||||
Quad *getQuad() const;
|
||||
|
||||
static bool validateFilter(const Filter &f, bool mipmapsAllowed);
|
||||
|
||||
static int getTotalMipmapCount(int w, int h);
|
||||
static int getTotalMipmapCount(int w, int h, int d);
|
||||
|
||||
static bool isClampZeroOrOne(WrapMode w) { return w == WRAP_CLAMP_ZERO || w == WRAP_CLAMP_ONE; }
|
||||
|
||||
static bool getConstant(const char *in, TextureType &out);
|
||||
static bool getConstant(TextureType in, const char *&out);
|
||||
static std::vector<std::string> getConstants(TextureType);
|
||||
|
||||
static bool getConstant(const char *in, FilterMode &out);
|
||||
static bool getConstant(FilterMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(FilterMode);
|
||||
|
||||
static bool getConstant(const char *in, WrapMode &out);
|
||||
static bool getConstant(WrapMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(WrapMode);
|
||||
|
||||
protected:
|
||||
|
||||
void initQuad();
|
||||
@@ -229,12 +232,7 @@ protected:
|
||||
int pixelWidth;
|
||||
int pixelHeight;
|
||||
|
||||
Filter filter;
|
||||
Wrap wrap;
|
||||
|
||||
float mipmapSharpness;
|
||||
|
||||
Optional<CompareMode> depthCompareMode;
|
||||
SamplerState samplerState;
|
||||
|
||||
StrongRef<Quad> quad;
|
||||
|
||||
@@ -245,12 +243,6 @@ private:
|
||||
static StringMap<TextureType, TEXTURE_MAX_ENUM>::Entry texTypeEntries[];
|
||||
static StringMap<TextureType, TEXTURE_MAX_ENUM> texTypes;
|
||||
|
||||
static StringMap<FilterMode, FILTER_MAX_ENUM>::Entry filterModeEntries[];
|
||||
static StringMap<FilterMode, FILTER_MAX_ENUM> filterModes;
|
||||
|
||||
static StringMap<WrapMode, WRAP_MAX_ENUM>::Entry wrapModeEntries[];
|
||||
static StringMap<WrapMode, WRAP_MAX_ENUM> wrapModes;
|
||||
|
||||
}; // Texture
|
||||
|
||||
} // graphics
|
||||
|
||||
@@ -35,9 +35,14 @@ Video::Video(Graphics *gfx, love::video::VideoStream *stream, float dpiscale)
|
||||
: stream(stream)
|
||||
, width(stream->getWidth() / dpiscale)
|
||||
, height(stream->getHeight() / dpiscale)
|
||||
, filter(Texture::defaultFilter)
|
||||
, samplerState()
|
||||
{
|
||||
filter.mipmap = Texture::FILTER_NONE;
|
||||
const SamplerState &defaultSampler = gfx->getDefaultSamplerState();
|
||||
samplerState.minFilter = defaultSampler.minFilter;
|
||||
samplerState.magFilter = defaultSampler.magFilter;
|
||||
samplerState.wrapU = defaultSampler.wrapU;
|
||||
samplerState.wrapV = defaultSampler.wrapV;
|
||||
samplerState.maxAnisotropy = defaultSampler.maxAnisotropy;
|
||||
|
||||
stream->fillBackBuffer();
|
||||
|
||||
@@ -74,15 +79,13 @@ Video::Video(Graphics *gfx, love::video::VideoStream *stream, float dpiscale)
|
||||
|
||||
const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
|
||||
|
||||
Texture::Wrap wrap; // Clamp wrap mode.
|
||||
Image::Settings settings;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Image *img = gfx->newImage(TEXTURE_2D, PIXELFORMAT_R8_UNORM, widths[i], heights[i], 1, settings);
|
||||
|
||||
img->setFilter(filter);
|
||||
img->setWrap(wrap);
|
||||
img->setSamplerState(samplerState);
|
||||
|
||||
size_t bpp = getPixelFormatSize(PIXELFORMAT_R8_UNORM);
|
||||
size_t size = bpp * widths[i] * heights[i];
|
||||
@@ -200,17 +203,21 @@ int Video::getPixelHeight() const
|
||||
return stream->getHeight();
|
||||
}
|
||||
|
||||
void Video::setFilter(const Texture::Filter &f)
|
||||
void Video::setSamplerState(const SamplerState &s)
|
||||
{
|
||||
for (const auto &image : images)
|
||||
image->setFilter(f);
|
||||
samplerState.minFilter = s.minFilter;
|
||||
samplerState.magFilter = s.magFilter;
|
||||
samplerState.wrapU = s.wrapU;
|
||||
samplerState.wrapV = s.wrapV;
|
||||
samplerState.maxAnisotropy = s.maxAnisotropy;
|
||||
|
||||
filter = f;
|
||||
for (const auto &image : images)
|
||||
image->setSamplerState(samplerState);
|
||||
}
|
||||
|
||||
const Texture::Filter &Video::getFilter() const
|
||||
const SamplerState &Video::getSamplerState() const
|
||||
{
|
||||
return filter;
|
||||
return samplerState;
|
||||
}
|
||||
|
||||
} // graphics
|
||||
|
||||
@@ -58,8 +58,8 @@ public:
|
||||
int getPixelWidth() const;
|
||||
int getPixelHeight() const;
|
||||
|
||||
void setFilter(const Texture::Filter &f);
|
||||
const Texture::Filter &getFilter() const;
|
||||
void setSamplerState(const SamplerState &s);
|
||||
const SamplerState &getSamplerState() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -70,7 +70,7 @@ private:
|
||||
int width;
|
||||
int height;
|
||||
|
||||
Texture::Filter filter;
|
||||
SamplerState samplerState;
|
||||
|
||||
Vertex vertices[4];
|
||||
|
||||
|
||||
@@ -239,10 +239,7 @@ bool Canvas::loadVolatile()
|
||||
if (GLAD_ANGLE_texture_usage)
|
||||
glTexParameteri(gltype, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
|
||||
|
||||
setFilter(filter);
|
||||
setWrap(wrap);
|
||||
setMipmapSharpness(mipmapSharpness);
|
||||
setDepthSampleMode(depthCompareMode);
|
||||
setSamplerState(samplerState);
|
||||
|
||||
while (glGetError() != GL_NO_ERROR)
|
||||
/* Clear the error buffer. */;
|
||||
@@ -320,113 +317,30 @@ void Canvas::unloadVolatile()
|
||||
setGraphicsMemorySize(0);
|
||||
}
|
||||
|
||||
void Canvas::setFilter(const Texture::Filter &f)
|
||||
void Canvas::setSamplerState(const SamplerState &s)
|
||||
{
|
||||
Texture::setFilter(f);
|
||||
Texture::setSamplerState(s);
|
||||
|
||||
if (samplerState.depthSampleMode.hasValue && !gl.isDepthCompareSampleSupported())
|
||||
throw love::Exception("Depth comparison sampling in shaders is not supported on this system.");
|
||||
|
||||
if (!OpenGL::hasTextureFilteringSupport(getPixelFormat()))
|
||||
{
|
||||
filter.mag = filter.min = FILTER_NEAREST;
|
||||
samplerState.magFilter = samplerState.minFilter = SamplerState::FILTER_NEAREST;
|
||||
|
||||
if (filter.mipmap == FILTER_LINEAR)
|
||||
filter.mipmap = FILTER_NEAREST;
|
||||
if (samplerState.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR)
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NEAREST;
|
||||
}
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
gl.setTextureFilter(texType, filter);
|
||||
}
|
||||
|
||||
bool Canvas::setWrap(const Texture::Wrap &w)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
bool success = true;
|
||||
bool forceclamp = texType == TEXTURE_CUBE;
|
||||
wrap = w;
|
||||
|
||||
// If we only have limited NPOT support then the wrap mode must be CLAMP.
|
||||
if ((GLAD_ES_VERSION_2_0 && !(GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot))
|
||||
&& (pixelWidth != nextP2(pixelWidth) || pixelHeight != nextP2(pixelHeight) || depth != nextP2(depth)))
|
||||
{
|
||||
forceclamp = true;
|
||||
}
|
||||
|
||||
if (forceclamp)
|
||||
{
|
||||
if (wrap.s != WRAP_CLAMP || wrap.t != WRAP_CLAMP || wrap.r != WRAP_CLAMP)
|
||||
success = false;
|
||||
|
||||
wrap.s = wrap.t = wrap.r = WRAP_CLAMP;
|
||||
}
|
||||
|
||||
if (!gl.isClampZeroOneTextureWrapSupported())
|
||||
{
|
||||
if (isClampZeroOrOne(wrap.s)) wrap.s = WRAP_CLAMP;
|
||||
if (isClampZeroOrOne(wrap.t)) wrap.t = WRAP_CLAMP;
|
||||
if (isClampZeroOrOne(wrap.r)) wrap.r = WRAP_CLAMP;
|
||||
samplerState.wrapU = samplerState.wrapV = samplerState.wrapW = SamplerState::WRAP_CLAMP;
|
||||
}
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
gl.setTextureWrap(texType, wrap);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Canvas::setMipmapSharpness(float sharpness)
|
||||
{
|
||||
if (!gl.isSamplerLODBiasSupported())
|
||||
return false;
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
float maxbias = gl.getMaxLODBias();
|
||||
if (maxbias > 0.01f)
|
||||
maxbias -= 0.0f;
|
||||
|
||||
mipmapSharpness = std::min(std::max(sharpness, -maxbias), maxbias);
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
|
||||
// negative bias is sharper
|
||||
glTexParameterf(gl.getGLTextureType(texType), GL_TEXTURE_LOD_BIAS, -mipmapSharpness);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Canvas::setDepthSampleMode(Optional<CompareMode> mode)
|
||||
{
|
||||
Texture::setDepthSampleMode(mode);
|
||||
|
||||
bool supported = gl.isDepthCompareSampleSupported();
|
||||
|
||||
if (mode.hasValue)
|
||||
{
|
||||
if (!supported)
|
||||
throw love::Exception("Depth comparison sampling in shaders is not supported on this system.");
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
gl.bindTextureToUnit(texType, texture, 0, false);
|
||||
GLenum gltextype = OpenGL::getGLTextureType(texType);
|
||||
|
||||
// See the comment in renderstate.h
|
||||
GLenum glmode = OpenGL::getGLCompareMode(getReversedCompareMode(mode.value));
|
||||
|
||||
glTexParameteri(gltextype, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glTexParameteri(gltextype, GL_TEXTURE_COMPARE_FUNC, glmode);
|
||||
|
||||
}
|
||||
else if (isPixelFormatDepth(format) && supported)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
gl.bindTextureToUnit(texType, texture, 0, false);
|
||||
GLenum gltextype = OpenGL::getGLTextureType(texType);
|
||||
|
||||
glTexParameteri(gltextype, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
|
||||
depthCompareMode = mode;
|
||||
gl.setSamplerState(texType, samplerState);
|
||||
}
|
||||
|
||||
ptrdiff_t Canvas::getHandle() const
|
||||
|
||||
@@ -47,10 +47,7 @@ public:
|
||||
void unloadVolatile() override;
|
||||
|
||||
// Implements Texture.
|
||||
void setFilter(const Texture::Filter &f) override;
|
||||
bool setWrap(const Texture::Wrap &w) override;
|
||||
bool setMipmapSharpness(float sharpness) override;
|
||||
void setDepthSampleMode(Optional<CompareMode> mode) override;
|
||||
void setSamplerState(const SamplerState &s) override;
|
||||
ptrdiff_t getHandle() const override;
|
||||
|
||||
love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect) override;
|
||||
|
||||
@@ -1470,12 +1470,9 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, boo
|
||||
glGenTextures(1, &texture);
|
||||
gl.bindTextureToUnit(TEXTURE_2D, texture, 0, false);
|
||||
|
||||
Texture::Filter f;
|
||||
f.min = f.mag = Texture::FILTER_NEAREST;
|
||||
gl.setTextureFilter(TEXTURE_2D, f);
|
||||
|
||||
Texture::Wrap w;
|
||||
gl.setTextureWrap(TEXTURE_2D, w);
|
||||
SamplerState s;
|
||||
s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST;
|
||||
gl.setSamplerState(TEXTURE_2D, s);
|
||||
|
||||
gl.rawTexStorage(TEXTURE_2D, 1, format, sRGB, 1, 1);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ void Image::loadDefaultTexture()
|
||||
usingDefaultTexture = true;
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
setFilter(filter);
|
||||
setSamplerState(samplerState);
|
||||
|
||||
bool isSRGB = false;
|
||||
gl.rawTexStorage(texType, 1, PIXELFORMAT_RGBA8_UNORM, isSRGB, 2, 2, 1);
|
||||
@@ -204,7 +204,7 @@ bool Image::loadVolatile()
|
||||
&& mipmapsType != MIPMAPS_DATA)
|
||||
{
|
||||
mipmapsType = MIPMAPS_NONE;
|
||||
filter.mipmap = FILTER_NONE;
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ bool Image::loadVolatile()
|
||||
&& (pixelWidth != nextP2(pixelWidth) || pixelHeight != nextP2(pixelHeight)))
|
||||
{
|
||||
mipmapsType = MIPMAPS_NONE;
|
||||
filter.mipmap = FILTER_NONE;
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
}
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
@@ -226,9 +226,7 @@ bool Image::loadVolatile()
|
||||
return true;
|
||||
}
|
||||
|
||||
setFilter(filter);
|
||||
setWrap(wrap);
|
||||
setMipmapSharpness(mipmapSharpness);
|
||||
setSamplerState(samplerState);
|
||||
|
||||
GLenum gltextype = OpenGL::getGLTextureType(texType);
|
||||
|
||||
@@ -282,85 +280,34 @@ ptrdiff_t Image::getHandle() const
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Image::setFilter(const Texture::Filter &f)
|
||||
void Image::setSamplerState(const SamplerState &s)
|
||||
{
|
||||
Texture::setFilter(f);
|
||||
Texture::setSamplerState(s);
|
||||
|
||||
if (!OpenGL::hasTextureFilteringSupport(getPixelFormat()))
|
||||
{
|
||||
filter.mag = filter.min = FILTER_NEAREST;
|
||||
samplerState.magFilter = samplerState.minFilter = SamplerState::FILTER_NEAREST;
|
||||
|
||||
if (filter.mipmap == FILTER_LINEAR)
|
||||
filter.mipmap = FILTER_NEAREST;
|
||||
if (samplerState.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR)
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NEAREST;
|
||||
}
|
||||
|
||||
// We don't want filtering or (attempted) mipmaps on the default texture.
|
||||
if (usingDefaultTexture)
|
||||
{
|
||||
filter.mipmap = FILTER_NONE;
|
||||
filter.min = filter.mag = FILTER_NEAREST;
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
samplerState.minFilter = samplerState.magFilter = SamplerState::FILTER_NEAREST;
|
||||
}
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
gl.setTextureFilter(texType, filter);
|
||||
}
|
||||
|
||||
bool Image::setWrap(const Texture::Wrap &w)
|
||||
{
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
bool success = true;
|
||||
bool forceclamp = texType == TEXTURE_CUBE;
|
||||
wrap = w;
|
||||
|
||||
// If we only have limited NPOT support then the wrap mode must be CLAMP.
|
||||
if ((GLAD_ES_VERSION_2_0 && !(GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot))
|
||||
&& (pixelWidth != nextP2(pixelWidth) || pixelHeight != nextP2(pixelHeight) || depth != nextP2(depth)))
|
||||
{
|
||||
forceclamp = true;
|
||||
}
|
||||
|
||||
if (forceclamp)
|
||||
{
|
||||
if (wrap.s != WRAP_CLAMP || wrap.t != WRAP_CLAMP || wrap.r != WRAP_CLAMP)
|
||||
success = false;
|
||||
|
||||
wrap.s = wrap.t = wrap.r = WRAP_CLAMP;
|
||||
}
|
||||
|
||||
if (!gl.isClampZeroOneTextureWrapSupported())
|
||||
{
|
||||
if (isClampZeroOrOne(wrap.s)) wrap.s = WRAP_CLAMP;
|
||||
if (isClampZeroOrOne(wrap.t)) wrap.t = WRAP_CLAMP;
|
||||
if (isClampZeroOrOne(wrap.r)) wrap.r = WRAP_CLAMP;
|
||||
samplerState.wrapU = samplerState.wrapV = samplerState.wrapW = SamplerState::WRAP_CLAMP;
|
||||
}
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
gl.setTextureWrap(texType, wrap);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Image::setMipmapSharpness(float sharpness)
|
||||
{
|
||||
if (!gl.isSamplerLODBiasSupported())
|
||||
return false;
|
||||
|
||||
Graphics::flushStreamDrawsGlobal();
|
||||
|
||||
float maxbias = gl.getMaxLODBias();
|
||||
|
||||
if (maxbias > 0.01f)
|
||||
maxbias -= 0.01f;
|
||||
|
||||
mipmapSharpness = std::min(std::max(sharpness, -maxbias), maxbias);
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
|
||||
// negative bias is sharper
|
||||
glTexParameterf(gl.getGLTextureType(texType), GL_TEXTURE_LOD_BIAS, -mipmapSharpness);
|
||||
|
||||
return true;
|
||||
gl.setSamplerState(texType, samplerState);
|
||||
}
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -49,10 +49,7 @@ public:
|
||||
|
||||
ptrdiff_t getHandle() const override;
|
||||
|
||||
void setFilter(const Texture::Filter &f) override;
|
||||
bool setWrap(const Texture::Wrap &w) override;
|
||||
|
||||
bool setMipmapSharpness(float sharpness) override;
|
||||
void setSamplerState(const SamplerState &s) override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -502,11 +502,9 @@ void OpenGL::createDefaultTexture()
|
||||
// untextured primitives vs images.
|
||||
const GLubyte pix[] = {255, 255, 255, 255};
|
||||
|
||||
Texture::Filter filter;
|
||||
filter.min = filter.mag = Texture::FILTER_NEAREST;
|
||||
|
||||
Texture::Wrap wrap;
|
||||
wrap.s = wrap.t = wrap.r = Texture::WRAP_CLAMP;
|
||||
SamplerState s;
|
||||
s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST;
|
||||
s.wrapU = s.wrapV = s.wrapW = SamplerState::WRAP_CLAMP;
|
||||
|
||||
for (int i = 0; i < TEXTURE_MAX_ENUM; i++)
|
||||
{
|
||||
@@ -522,8 +520,7 @@ void OpenGL::createDefaultTexture()
|
||||
glGenTextures(1, &state.defaultTexture[type]);
|
||||
bindTextureToUnit(type, state.defaultTexture[type], 0, false);
|
||||
|
||||
setTextureWrap(type, wrap);
|
||||
setTextureFilter(type, filter);
|
||||
setSamplerState(type, s);
|
||||
|
||||
bool isSRGB = false;
|
||||
rawTexStorage(type, 1, PIXELFORMAT_RGBA8_UNORM, isSRGB, 1, 1);
|
||||
@@ -1050,52 +1047,19 @@ void OpenGL::deleteTexture(GLuint texture)
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
void OpenGL::setTextureFilter(TextureType target, graphics::Texture::Filter &f)
|
||||
{
|
||||
GLint gmin = f.min == Texture::FILTER_NEAREST ? GL_NEAREST : GL_LINEAR;
|
||||
GLint gmag = f.mag == Texture::FILTER_NEAREST ? GL_NEAREST : GL_LINEAR;
|
||||
|
||||
if (f.mipmap != Texture::FILTER_NONE)
|
||||
{
|
||||
if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_NEAREST)
|
||||
gmin = GL_NEAREST_MIPMAP_NEAREST;
|
||||
else if (f.min == Texture::FILTER_NEAREST && f.mipmap == Texture::FILTER_LINEAR)
|
||||
gmin = GL_NEAREST_MIPMAP_LINEAR;
|
||||
else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_NEAREST)
|
||||
gmin = GL_LINEAR_MIPMAP_NEAREST;
|
||||
else if (f.min == Texture::FILTER_LINEAR && f.mipmap == Texture::FILTER_LINEAR)
|
||||
gmin = GL_LINEAR_MIPMAP_LINEAR;
|
||||
else
|
||||
gmin = GL_LINEAR;
|
||||
}
|
||||
|
||||
GLenum gltarget = getGLTextureType(target);
|
||||
|
||||
glTexParameteri(gltarget, GL_TEXTURE_MIN_FILTER, gmin);
|
||||
glTexParameteri(gltarget, GL_TEXTURE_MAG_FILTER, gmag);
|
||||
|
||||
if (GLAD_EXT_texture_filter_anisotropic)
|
||||
{
|
||||
f.anisotropy = std::min(std::max(f.anisotropy, 1.0f), maxAnisotropy);
|
||||
glTexParameterf(gltarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, f.anisotropy);
|
||||
}
|
||||
else
|
||||
f.anisotropy = 1.0f;
|
||||
}
|
||||
|
||||
GLint OpenGL::getGLWrapMode(Texture::WrapMode wmode)
|
||||
GLint OpenGL::getGLWrapMode(SamplerState::WrapMode wmode)
|
||||
{
|
||||
switch (wmode)
|
||||
{
|
||||
case Texture::WRAP_CLAMP:
|
||||
case SamplerState::WRAP_CLAMP:
|
||||
default:
|
||||
return GL_CLAMP_TO_EDGE;
|
||||
case Texture::WRAP_CLAMP_ZERO:
|
||||
case Texture::WRAP_CLAMP_ONE:
|
||||
case SamplerState::WRAP_CLAMP_ZERO:
|
||||
case SamplerState::WRAP_CLAMP_ONE:
|
||||
return GL_CLAMP_TO_BORDER;
|
||||
case Texture::WRAP_REPEAT:
|
||||
case SamplerState::WRAP_REPEAT:
|
||||
return GL_REPEAT;
|
||||
case Texture::WRAP_MIRRORED_REPEAT:
|
||||
case SamplerState::WRAP_MIRRORED_REPEAT:
|
||||
return GL_MIRRORED_REPEAT;
|
||||
}
|
||||
}
|
||||
@@ -1125,29 +1089,111 @@ GLint OpenGL::getGLCompareMode(CompareMode mode)
|
||||
}
|
||||
}
|
||||
|
||||
static bool isClampOne(Texture::WrapMode mode)
|
||||
static bool isClampOne(SamplerState::WrapMode mode)
|
||||
{
|
||||
return mode == Texture::WRAP_CLAMP_ONE;
|
||||
return mode == SamplerState::WRAP_CLAMP_ONE;
|
||||
}
|
||||
|
||||
void OpenGL::setTextureWrap(TextureType target, const graphics::Texture::Wrap &w)
|
||||
void OpenGL::setSamplerState(TextureType target, SamplerState &s)
|
||||
{
|
||||
GLenum textype = getGLTextureType(target);
|
||||
GLenum gltarget = getGLTextureType(target);
|
||||
|
||||
if (Texture::isClampZeroOrOne(w.s) || Texture::isClampZeroOrOne(w.t) || Texture::isClampZeroOrOne(w.r))
|
||||
GLint gmin = s.minFilter == SamplerState::FILTER_NEAREST ? GL_NEAREST : GL_LINEAR;
|
||||
GLint gmag = s.magFilter == SamplerState::FILTER_NEAREST ? GL_NEAREST : GL_LINEAR;
|
||||
|
||||
if (s.mipmapFilter != SamplerState::MIPMAP_FILTER_NONE)
|
||||
{
|
||||
GLfloat c[] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
if (isClampOne(w.s) || isClampOne(w.t) || isClampOne(w.r))
|
||||
c[0] = c[1] = c[2] = c[3] = 1.0f;
|
||||
|
||||
glTexParameterfv(textype, GL_TEXTURE_BORDER_COLOR, c);
|
||||
if (s.minFilter == SamplerState::FILTER_NEAREST && s.mipmapFilter == SamplerState::MIPMAP_FILTER_NEAREST)
|
||||
gmin = GL_NEAREST_MIPMAP_NEAREST;
|
||||
else if (s.minFilter == SamplerState::FILTER_NEAREST && s.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR)
|
||||
gmin = GL_NEAREST_MIPMAP_LINEAR;
|
||||
else if (s.minFilter == SamplerState::FILTER_LINEAR && s.mipmapFilter == SamplerState::MIPMAP_FILTER_NEAREST)
|
||||
gmin = GL_LINEAR_MIPMAP_NEAREST;
|
||||
else if (s.minFilter == SamplerState::FILTER_LINEAR && s.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR)
|
||||
gmin = GL_LINEAR_MIPMAP_LINEAR;
|
||||
}
|
||||
|
||||
glTexParameteri(textype, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s));
|
||||
glTexParameteri(textype, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t));
|
||||
glTexParameteri(gltarget, GL_TEXTURE_MIN_FILTER, gmin);
|
||||
glTexParameteri(gltarget, GL_TEXTURE_MAG_FILTER, gmag);
|
||||
|
||||
if (!isClampZeroOneTextureWrapSupported())
|
||||
{
|
||||
if (SamplerState::isClampZeroOrOne(s.wrapU)) s.wrapU = SamplerState::WRAP_CLAMP;
|
||||
if (SamplerState::isClampZeroOrOne(s.wrapV)) s.wrapV = SamplerState::WRAP_CLAMP;
|
||||
if (SamplerState::isClampZeroOrOne(s.wrapW)) s.wrapW = SamplerState::WRAP_CLAMP;
|
||||
}
|
||||
|
||||
if (SamplerState::isClampZeroOrOne(s.wrapU) || SamplerState::isClampZeroOrOne(s.wrapV) || SamplerState::isClampZeroOrOne(s.wrapW))
|
||||
{
|
||||
GLfloat c[] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
if (isClampOne(s.wrapU) || isClampOne(s.wrapU) || isClampOne(s.wrapV))
|
||||
c[0] = c[1] = c[2] = c[3] = 1.0f;
|
||||
|
||||
glTexParameterfv(gltarget, GL_TEXTURE_BORDER_COLOR, c);
|
||||
}
|
||||
|
||||
glTexParameteri(gltarget, GL_TEXTURE_WRAP_S, getGLWrapMode(s.wrapU));
|
||||
glTexParameteri(gltarget, GL_TEXTURE_WRAP_T, getGLWrapMode(s.wrapV));
|
||||
|
||||
if (target == TEXTURE_VOLUME)
|
||||
glTexParameteri(textype, GL_TEXTURE_WRAP_R, getGLWrapMode(w.r));
|
||||
glTexParameteri(gltarget, GL_TEXTURE_WRAP_R, getGLWrapMode(s.wrapW));
|
||||
|
||||
if (isSamplerLODBiasSupported())
|
||||
{
|
||||
float maxbias = getMaxLODBias();
|
||||
if (maxbias > 0.01f)
|
||||
maxbias -= 0.01f;
|
||||
|
||||
s.lodBias = std::min(std::max(s.lodBias, -maxbias), maxbias);
|
||||
|
||||
glTexParameterf(gltarget, GL_TEXTURE_LOD_BIAS, s.lodBias);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.lodBias = 0.0f;
|
||||
}
|
||||
|
||||
if (GLAD_EXT_texture_filter_anisotropic)
|
||||
{
|
||||
uint8 maxAniso = (uint8) std::min(maxAnisotropy, (float)LOVE_UINT8_MAX);
|
||||
s.maxAnisotropy = std::min(std::max(s.maxAnisotropy, (uint8)1), maxAniso);
|
||||
glTexParameteri(gltarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, s.maxAnisotropy);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.maxAnisotropy = 1;
|
||||
}
|
||||
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0)
|
||||
{
|
||||
glTexParameterf(gltarget, GL_TEXTURE_MIN_LOD, (float)s.minLod);
|
||||
glTexParameterf(gltarget, GL_TEXTURE_MAX_LOD, (float)s.maxLod);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.minLod = 0;
|
||||
s.maxLod = LOVE_UINT8_MAX;
|
||||
}
|
||||
|
||||
if (isDepthCompareSampleSupported())
|
||||
{
|
||||
if (s.depthSampleMode.hasValue)
|
||||
{
|
||||
// See the comment in renderstate.h
|
||||
GLenum glmode = getGLCompareMode(getReversedCompareMode(s.depthSampleMode.value));
|
||||
|
||||
glTexParameteri(gltarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glTexParameteri(gltarget, GL_TEXTURE_COMPARE_FUNC, glmode);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(gltarget, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s.depthSampleMode.hasValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth)
|
||||
|
||||
@@ -329,16 +329,9 @@ public:
|
||||
void deleteTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Sets the texture filter mode for the currently bound texture.
|
||||
* The anisotropy parameter of the argument is set to the actual amount of
|
||||
* anisotropy that was used.
|
||||
* Sets sampler state parameters for the currently bound texture.
|
||||
**/
|
||||
void setTextureFilter(TextureType target, graphics::Texture::Filter &f);
|
||||
|
||||
/**
|
||||
* Sets the texture wrap mode for the currently bound texture.
|
||||
**/
|
||||
void setTextureWrap(TextureType target, const graphics::Texture::Wrap &w);
|
||||
void setSamplerState(TextureType target, SamplerState &s);
|
||||
|
||||
/**
|
||||
* Equivalent to glTexStorage2D/3D on platforms that support it. Equivalent
|
||||
@@ -407,7 +400,7 @@ public:
|
||||
static GLenum getGLVertexDataType(vertex::DataType type, GLboolean &normalized, bool &intformat);
|
||||
static GLenum getGLBufferUsage(vertex::Usage usage);
|
||||
static GLenum getGLTextureType(TextureType type);
|
||||
static GLint getGLWrapMode(Texture::WrapMode wmode);
|
||||
static GLint getGLWrapMode(SamplerState::WrapMode wmode);
|
||||
static GLint getGLCompareMode(CompareMode mode);
|
||||
|
||||
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
|
||||
|
||||
@@ -588,6 +588,7 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
|
||||
|
||||
if (tex != nullptr)
|
||||
{
|
||||
const SamplerState &sampler = tex->getSamplerState();
|
||||
if (!tex->isReadable())
|
||||
{
|
||||
if (internalUpdate)
|
||||
@@ -595,7 +596,7 @@ void Shader::sendTextures(const UniformInfo *info, Texture **textures, int count
|
||||
else
|
||||
throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
|
||||
}
|
||||
else if (info->isDepthSampler != tex->getDepthSampleMode().hasValue)
|
||||
else if (info->isDepthSampler != sampler.depthSampleMode.hasValue)
|
||||
{
|
||||
if (internalUpdate)
|
||||
continue;
|
||||
|
||||
@@ -139,33 +139,33 @@ int w_Font_getLineHeight(lua_State *L)
|
||||
int w_Font_setFilter(lua_State *L)
|
||||
{
|
||||
Font *t = luax_checkfont(L, 1);
|
||||
Texture::Filter f = t->getFilter();
|
||||
SamplerState s = t->getSamplerState();
|
||||
|
||||
const char *minstr = luaL_checkstring(L, 2);
|
||||
const char *magstr = luaL_optstring(L, 3, minstr);
|
||||
|
||||
if (!Texture::getConstant(minstr, f.min))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.min), minstr);
|
||||
if (!Texture::getConstant(magstr, f.mag))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.mag), magstr);
|
||||
if (!SamplerState::getConstant(minstr, s.minFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.minFilter), minstr);
|
||||
if (!SamplerState::getConstant(magstr, s.magFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.magFilter), magstr);
|
||||
|
||||
f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
|
||||
s.maxAnisotropy = std::min(std::max(1, (int) luaL_optnumber(L, 4, 1.0)), LOVE_UINT8_MAX);
|
||||
|
||||
luax_catchexcept(L, [&](){ t->setFilter(f); });
|
||||
luax_catchexcept(L, [&](){ t->setSamplerState(s); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Font_getFilter(lua_State *L)
|
||||
{
|
||||
Font *t = luax_checkfont(L, 1);
|
||||
const Texture::Filter f = t->getFilter();
|
||||
const SamplerState &s = t->getSamplerState();
|
||||
const char *minstr;
|
||||
const char *magstr;
|
||||
Texture::getConstant(f.min, minstr);
|
||||
Texture::getConstant(f.mag, magstr);
|
||||
SamplerState::getConstant(s.minFilter, minstr);
|
||||
SamplerState::getConstant(s.magFilter, magstr);
|
||||
lua_pushstring(L, minstr);
|
||||
lua_pushstring(L, magstr);
|
||||
lua_pushnumber(L, f.anisotropy);
|
||||
lua_pushnumber(L, s.maxAnisotropy);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -1102,7 +1102,7 @@ int w_newFont(lua_State *L)
|
||||
love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1);
|
||||
|
||||
luax_catchexcept(L, [&]() {
|
||||
font = instance()->newFont(rasterizer, instance()->getDefaultFilter()); }
|
||||
font = instance()->newFont(rasterizer); }
|
||||
);
|
||||
|
||||
// Push the type.
|
||||
@@ -1115,9 +1115,6 @@ int w_newImageFont(lua_State *L)
|
||||
{
|
||||
luax_checkgraphicscreated(L);
|
||||
|
||||
// filter for glyphs
|
||||
Texture::Filter filter = instance()->getDefaultFilter();
|
||||
|
||||
// Convert to Rasterizer if necessary.
|
||||
if (!luax_istype(L, 1, love::font::Rasterizer::type))
|
||||
{
|
||||
@@ -1133,7 +1130,7 @@ int w_newImageFont(lua_State *L)
|
||||
love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1);
|
||||
|
||||
// Create the font.
|
||||
Font *font = instance()->newFont(rasterizer, filter);
|
||||
Font *font = instance()->newFont(rasterizer);
|
||||
|
||||
// Push the type.
|
||||
luax_pushtype(L, font);
|
||||
@@ -1935,69 +1932,65 @@ int w_getBlendState(lua_State *L)
|
||||
|
||||
int w_setDefaultFilter(lua_State *L)
|
||||
{
|
||||
Texture::Filter f;
|
||||
SamplerState s = instance()->getDefaultSamplerState();
|
||||
|
||||
const char *minstr = luaL_checkstring(L, 1);
|
||||
const char *magstr = luaL_optstring(L, 2, minstr);
|
||||
|
||||
if (!Texture::getConstant(minstr, f.min))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.min), minstr);
|
||||
if (!Texture::getConstant(magstr, f.mag))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.mag), magstr);
|
||||
if (!SamplerState::getConstant(minstr, s.minFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.minFilter), minstr);
|
||||
if (!SamplerState::getConstant(magstr, s.magFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.magFilter), magstr);
|
||||
|
||||
f.anisotropy = (float) luaL_optnumber(L, 3, 1.0);
|
||||
|
||||
instance()->setDefaultFilter(f);
|
||||
s.maxAnisotropy = std::min(std::max(1, (int) luaL_optnumber(L, 3, 1.0)), LOVE_UINT8_MAX);
|
||||
|
||||
instance()->setDefaultSamplerState(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getDefaultFilter(lua_State *L)
|
||||
{
|
||||
const Texture::Filter &f = instance()->getDefaultFilter();
|
||||
const SamplerState &s = instance()->getDefaultSamplerState();
|
||||
const char *minstr;
|
||||
const char *magstr;
|
||||
if (!Texture::getConstant(f.min, minstr))
|
||||
if (!SamplerState::getConstant(s.minFilter, minstr))
|
||||
return luaL_error(L, "Unknown minification filter mode");
|
||||
if (!Texture::getConstant(f.mag, magstr))
|
||||
if (!SamplerState::getConstant(s.magFilter, magstr))
|
||||
return luaL_error(L, "Unknown magnification filter mode");
|
||||
lua_pushstring(L, minstr);
|
||||
lua_pushstring(L, magstr);
|
||||
lua_pushnumber(L, f.anisotropy);
|
||||
lua_pushnumber(L, s.maxAnisotropy);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int w_setDefaultMipmapFilter(lua_State *L)
|
||||
{
|
||||
Texture::FilterMode filter = Texture::FILTER_NONE;
|
||||
SamplerState s = instance()->getDefaultSamplerState();
|
||||
s.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 1);
|
||||
if (!Texture::getConstant(str, filter))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(filter), str);
|
||||
if (!SamplerState::getConstant(str, s.mipmapFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.mipmapFilter), str);
|
||||
}
|
||||
|
||||
float sharpness = (float) luaL_optnumber(L, 2, 0);
|
||||
|
||||
instance()->setDefaultMipmapFilter(filter, sharpness);
|
||||
s.lodBias = -((float) luaL_optnumber(L, 2, 0.0));
|
||||
|
||||
instance()->setDefaultSamplerState(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getDefaultMipmapFilter(lua_State *L)
|
||||
{
|
||||
Texture::FilterMode filter;
|
||||
float sharpness;
|
||||
|
||||
instance()->getDefaultMipmapFilter(&filter, &sharpness);
|
||||
const SamplerState &s = instance()->getDefaultSamplerState();
|
||||
|
||||
const char *str;
|
||||
if (Texture::getConstant(filter, str))
|
||||
if (SamplerState::getConstant(s.mipmapFilter, str))
|
||||
lua_pushstring(L, str);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
lua_pushnumber(L, sharpness);
|
||||
lua_pushnumber(L, -s.lodBias);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -132,111 +132,111 @@ int w_Texture_getDPIScale(lua_State *L)
|
||||
int w_Texture_setFilter(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
Texture::Filter f = t->getFilter();
|
||||
SamplerState s = t->getSamplerState();
|
||||
|
||||
const char *minstr = luaL_checkstring(L, 2);
|
||||
const char *magstr = luaL_optstring(L, 3, minstr);
|
||||
|
||||
if (!Texture::getConstant(minstr, f.min))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.min), minstr);
|
||||
if (!Texture::getConstant(magstr, f.mag))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.mag), magstr);
|
||||
if (!SamplerState::getConstant(minstr, s.minFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.minFilter), minstr);
|
||||
if (!SamplerState::getConstant(magstr, s.magFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.magFilter), magstr);
|
||||
|
||||
f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
|
||||
s.maxAnisotropy = std::min(std::max(1, (int) luaL_optnumber(L, 4, 1.0)), LOVE_UINT8_MAX);
|
||||
|
||||
luax_catchexcept(L, [&](){ t->setFilter(f); });
|
||||
luax_catchexcept(L, [&](){ t->setSamplerState(s); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Texture_getFilter(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
const Texture::Filter f = t->getFilter();
|
||||
const SamplerState &s = t->getSamplerState();
|
||||
|
||||
const char *minstr = nullptr;
|
||||
const char *magstr = nullptr;
|
||||
|
||||
if (!Texture::getConstant(f.min, minstr))
|
||||
if (!SamplerState::getConstant(s.minFilter, minstr))
|
||||
return luaL_error(L, "Unknown filter mode.");
|
||||
if (!Texture::getConstant(f.mag, magstr))
|
||||
if (!SamplerState::getConstant(s.magFilter, magstr))
|
||||
return luaL_error(L, "Unknown filter mode.");
|
||||
|
||||
lua_pushstring(L, minstr);
|
||||
lua_pushstring(L, magstr);
|
||||
lua_pushnumber(L, f.anisotropy);
|
||||
lua_pushnumber(L, s.maxAnisotropy);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int w_Texture_setMipmapFilter(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
Texture::Filter f = t->getFilter();
|
||||
SamplerState s = t->getSamplerState();
|
||||
|
||||
// Mipmapping is disabled if no argument is given.
|
||||
if (lua_isnoneornil(L, 2))
|
||||
f.mipmap = Texture::FILTER_NONE; // mipmapping is disabled if no argument is given
|
||||
s.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
else
|
||||
{
|
||||
const char *mipmapstr = luaL_checkstring(L, 2);
|
||||
if (!Texture::getConstant(mipmapstr, f.mipmap))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.mipmap), mipmapstr);
|
||||
if (!SamplerState::getConstant(mipmapstr, s.mipmapFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.mipmapFilter), mipmapstr);
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&](){ t->setFilter(f); });
|
||||
t->setMipmapSharpness((float) luaL_optnumber(L, 3, 0.0));
|
||||
s.lodBias = -((float) luaL_optnumber(L, 3, 0.0));
|
||||
|
||||
luax_catchexcept(L, [&](){ t->setSamplerState(s); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Texture_getMipmapFilter(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
|
||||
const Texture::Filter &f = t->getFilter();
|
||||
const SamplerState &s = t->getSamplerState();
|
||||
|
||||
const char *mipmapstr;
|
||||
if (Texture::getConstant(f.mipmap, mipmapstr))
|
||||
if (SamplerState::getConstant(s.mipmapFilter, mipmapstr))
|
||||
lua_pushstring(L, mipmapstr);
|
||||
else
|
||||
lua_pushnil(L); // only return a mipmap filter if mipmapping is enabled
|
||||
|
||||
lua_pushnumber(L, t->getMipmapSharpness());
|
||||
lua_pushnumber(L, -s.lodBias);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_Texture_setWrap(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
Texture::Wrap w;
|
||||
SamplerState s = t->getSamplerState();
|
||||
|
||||
const char *sstr = luaL_checkstring(L, 2);
|
||||
const char *tstr = luaL_optstring(L, 3, sstr);
|
||||
const char *rstr = luaL_optstring(L, 4, sstr);
|
||||
|
||||
if (!Texture::getConstant(sstr, w.s))
|
||||
return luax_enumerror(L, "wrap mode", Texture::getConstants(w.s), sstr);
|
||||
if (!Texture::getConstant(tstr, w.t))
|
||||
return luax_enumerror(L, "wrap mode", Texture::getConstants(w.t), tstr);
|
||||
if (!Texture::getConstant(rstr, w.r))
|
||||
return luax_enumerror(L, "wrap mode", Texture::getConstants(w.r), rstr);
|
||||
if (!SamplerState::getConstant(sstr, s.wrapU))
|
||||
return luax_enumerror(L, "wrap mode", SamplerState::getConstants(s.wrapU), sstr);
|
||||
if (!SamplerState::getConstant(tstr, s.wrapV))
|
||||
return luax_enumerror(L, "wrap mode", SamplerState::getConstants(s.wrapV), tstr);
|
||||
if (!SamplerState::getConstant(rstr, s.wrapW))
|
||||
return luax_enumerror(L, "wrap mode", SamplerState::getConstants(s.wrapW), rstr);
|
||||
|
||||
luax_pushboolean(L, t->setWrap(w));
|
||||
luax_catchexcept(L, [&](){ t->setSamplerState(s); });
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Texture_getWrap(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
const Texture::Wrap w = t->getWrap();
|
||||
const SamplerState &s = t->getSamplerState();
|
||||
|
||||
const char *sstr = nullptr;
|
||||
const char *tstr = nullptr;
|
||||
const char *rstr = nullptr;
|
||||
|
||||
if (!Texture::getConstant(w.s, sstr))
|
||||
if (!SamplerState::getConstant(s.wrapU, sstr))
|
||||
return luaL_error(L, "Unknown wrap mode.");
|
||||
if (!Texture::getConstant(w.t, tstr))
|
||||
if (!SamplerState::getConstant(s.wrapV, tstr))
|
||||
return luaL_error(L, "Unknown wrap mode.");
|
||||
if (!Texture::getConstant(w.r, rstr))
|
||||
if (!SamplerState::getConstant(s.wrapW, rstr))
|
||||
return luaL_error(L, "Unknown wrap mode.");
|
||||
|
||||
lua_pushstring(L, sstr);
|
||||
@@ -267,30 +267,31 @@ int w_Texture_isReadable(lua_State *L)
|
||||
int w_Texture_setDepthSampleMode(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
SamplerState s = t->getSamplerState();
|
||||
|
||||
Optional<CompareMode> mode;
|
||||
s.depthSampleMode.hasValue = false;
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 2);
|
||||
|
||||
mode.hasValue = true;
|
||||
if (!getConstant(str, mode.value))
|
||||
return luax_enumerror(L, "compare mode", getConstants(mode.value), str);
|
||||
s.depthSampleMode.hasValue = true;
|
||||
if (!getConstant(str, s.depthSampleMode.value))
|
||||
return luax_enumerror(L, "compare mode", getConstants(s.depthSampleMode.value), str);
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&]() { t->setDepthSampleMode(mode); });
|
||||
luax_catchexcept(L, [&](){ t->setSamplerState(s); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Texture_getDepthSampleMode(lua_State *L)
|
||||
{
|
||||
Texture *t = luax_checktexture(L, 1);
|
||||
Optional<CompareMode> mode = t->getDepthSampleMode();
|
||||
const SamplerState &s = t->getSamplerState();
|
||||
|
||||
if (mode.hasValue)
|
||||
if (s.depthSampleMode.hasValue)
|
||||
{
|
||||
const char *str = nullptr;
|
||||
if (!getConstant(mode.value, str))
|
||||
if (!getConstant(s.depthSampleMode.value, str))
|
||||
return luaL_error(L, "Unknown compare mode.");
|
||||
lua_pushstring(L, str);
|
||||
}
|
||||
|
||||
@@ -113,38 +113,38 @@ int w_Video_getPixelDimensions(lua_State *L)
|
||||
int w_Video_setFilter(lua_State *L)
|
||||
{
|
||||
Video *video = luax_checkvideo(L, 1);
|
||||
Texture::Filter f = video->getFilter();
|
||||
SamplerState s = video->getSamplerState();
|
||||
|
||||
const char *minstr = luaL_checkstring(L, 2);
|
||||
const char *magstr = luaL_optstring(L, 3, minstr);
|
||||
|
||||
if (!Texture::getConstant(minstr, f.min))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.min), minstr);
|
||||
if (!Texture::getConstant(magstr, f.mag))
|
||||
return luax_enumerror(L, "filter mode", Texture::getConstants(f.mag), magstr);
|
||||
if (!SamplerState::getConstant(minstr, s.minFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.minFilter), minstr);
|
||||
if (!SamplerState::getConstant(magstr, s.magFilter))
|
||||
return luax_enumerror(L, "filter mode", SamplerState::getConstants(s.magFilter), magstr);
|
||||
|
||||
f.anisotropy = (float) luaL_optnumber(L, 4, 1.0);
|
||||
s.maxAnisotropy = std::min(std::max(1, (int) luaL_optnumber(L, 4, 1.0)), LOVE_UINT8_MAX);
|
||||
|
||||
luax_catchexcept(L, [&](){ video->setFilter(f); });
|
||||
luax_catchexcept(L, [&](){ video->setSamplerState(s); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Video_getFilter(lua_State *L)
|
||||
{
|
||||
Video *video = luax_checkvideo(L, 1);
|
||||
const Texture::Filter f = video->getFilter();
|
||||
const SamplerState &s = video->getSamplerState();
|
||||
|
||||
const char *minstr = nullptr;
|
||||
const char *magstr = nullptr;
|
||||
|
||||
if (!Texture::getConstant(f.min, minstr))
|
||||
if (!SamplerState::getConstant(s.minFilter, minstr))
|
||||
return luaL_error(L, "Unknown filter mode.");
|
||||
if (!Texture::getConstant(f.mag, magstr))
|
||||
if (!SamplerState::getConstant(s.magFilter, magstr))
|
||||
return luaL_error(L, "Unknown filter mode.");
|
||||
|
||||
lua_pushstring(L, minstr);
|
||||
lua_pushstring(L, magstr);
|
||||
lua_pushnumber(L, f.anisotropy);
|
||||
lua_pushnumber(L, s.maxAnisotropy);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user