Refactor sampler state parameters for textures.

This commit is contained in:
Alex Szpakowski
2020-02-02 22:26:28 -04:00
parent f24b1aa377
commit f9248d478c
23 changed files with 473 additions and 585 deletions
-3
View File
@@ -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();
+14 -10
View File
@@ -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
+4 -4
View File
@@ -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;
+10 -28
View File
@@ -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)
+7 -16
View File
@@ -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
-3
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
+53 -61
View File
@@ -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
+18 -11
View File
@@ -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
+3 -3
View File
@@ -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];
+11 -97
View File
@@ -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
+1 -4
View File
@@ -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;
+3 -6
View File
@@ -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);
}
+13 -66
View File
@@ -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
+1 -4
View File
@@ -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:
+105 -59
View File
@@ -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)
+3 -10
View File
@@ -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);
+2 -1
View File
@@ -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;
+11 -11
View File
@@ -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;
}
+22 -29
View File
@@ -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;
}
+42 -41
View File
@@ -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);
}
+11 -11
View File
@@ -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;
}