mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Begin unification of Canvases and Images.
This commit is contained in:
@@ -102,7 +102,7 @@ Canvas::~Canvas()
|
||||
{
|
||||
}
|
||||
|
||||
Canvas::MipmapMode Canvas::getMipmapMode() const
|
||||
Texture::MipmapsMode Canvas::getMipmapsMode() const
|
||||
{
|
||||
return settings.mipmaps;
|
||||
}
|
||||
@@ -141,21 +141,6 @@ love::image::ImageData *Canvas::newImageData(love::image::Image *module, int sli
|
||||
return module->newImageData(r.w, r.h, dataformat);
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(const char *in, MipmapMode &out)
|
||||
{
|
||||
return mipmapModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(MipmapMode in, const char *&out)
|
||||
{
|
||||
return mipmapModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> Canvas::getConstants(MipmapMode)
|
||||
{
|
||||
return mipmapModes.getNames();
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(const char *in, SettingType &out)
|
||||
{
|
||||
return settingTypes.find(in, out);
|
||||
@@ -178,15 +163,6 @@ std::vector<std::string> Canvas::getConstants(SettingType)
|
||||
return settingTypes.getNames();
|
||||
}
|
||||
|
||||
StringMap<Canvas::MipmapMode, Canvas::MIPMAPS_MAX_ENUM>::Entry Canvas::mipmapEntries[] =
|
||||
{
|
||||
{ "none", MIPMAPS_NONE },
|
||||
{ "manual", MIPMAPS_MANUAL },
|
||||
{ "auto", MIPMAPS_AUTO },
|
||||
};
|
||||
|
||||
StringMap<Canvas::MipmapMode, Canvas::MIPMAPS_MAX_ENUM> Canvas::mipmapModes(Canvas::mipmapEntries, sizeof(Canvas::mipmapEntries));
|
||||
|
||||
StringMap<Canvas::SettingType, Canvas::SETTING_MAX_ENUM>::Entry Canvas::settingTypeEntries[] =
|
||||
{
|
||||
// Width / height / layers are currently omittted because they're separate
|
||||
|
||||
@@ -39,14 +39,6 @@ public:
|
||||
|
||||
static love::Type type;
|
||||
|
||||
enum MipmapMode
|
||||
{
|
||||
MIPMAPS_NONE,
|
||||
MIPMAPS_MANUAL,
|
||||
MIPMAPS_AUTO,
|
||||
MIPMAPS_MAX_ENUM
|
||||
};
|
||||
|
||||
enum SettingType
|
||||
{
|
||||
SETTING_WIDTH,
|
||||
@@ -66,7 +58,7 @@ public:
|
||||
int width = 1;
|
||||
int height = 1;
|
||||
int layers = 1; // depth for 3D textures
|
||||
MipmapMode mipmaps = MIPMAPS_NONE;
|
||||
MipmapsMode mipmaps = MIPMAPS_NONE;
|
||||
PixelFormat format = PIXELFORMAT_NORMAL;
|
||||
TextureType type = TEXTURE_2D;
|
||||
float dpiScale = 1.0f;
|
||||
@@ -77,14 +69,10 @@ public:
|
||||
Canvas(const Settings &settings);
|
||||
virtual ~Canvas();
|
||||
|
||||
MipmapMode getMipmapMode() const;
|
||||
MipmapsMode getMipmapsMode() const;
|
||||
|
||||
virtual love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect);
|
||||
|
||||
static bool getConstant(const char *in, MipmapMode &out);
|
||||
static bool getConstant(MipmapMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(MipmapMode);
|
||||
|
||||
static bool getConstant(const char *in, SettingType &out);
|
||||
static bool getConstant(SettingType in, const char *&out);
|
||||
static const char *getConstant(SettingType in);
|
||||
@@ -96,8 +84,8 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<MipmapMode, MIPMAPS_MAX_ENUM>::Entry mipmapEntries[];
|
||||
static StringMap<MipmapMode, MIPMAPS_MAX_ENUM> mipmapModes;
|
||||
static StringMap<MipmapsMode, MIPMAPS_MAX_ENUM>::Entry mipmapEntries[];
|
||||
static StringMap<MipmapsMode, MIPMAPS_MAX_ENUM> mipmapModes;
|
||||
|
||||
static StringMap<SettingType, SETTING_MAX_ENUM>::Entry settingTypeEntries[];
|
||||
static StringMap<SettingType, SETTING_MAX_ENUM> settingTypes;
|
||||
|
||||
@@ -116,7 +116,7 @@ Graphics::Graphics()
|
||||
, writingToStencil(false)
|
||||
, streamBufferState()
|
||||
, projectionMatrix()
|
||||
, canvasSwitchCount(0)
|
||||
, renderTargetSwitchCount(0)
|
||||
, drawCalls(0)
|
||||
, drawCallsBatched(0)
|
||||
, quadIndexBuffer(nullptr)
|
||||
@@ -335,8 +335,8 @@ int Graphics::getPixelHeight() const
|
||||
double Graphics::getCurrentDPIScale() const
|
||||
{
|
||||
const auto &rt = states.back().renderTargets.getFirstTarget();
|
||||
if (rt.canvas.get())
|
||||
return rt.canvas->getDPIScale();
|
||||
if (rt.texture.get())
|
||||
return rt.texture->getDPIScale();
|
||||
|
||||
return getScreenDPIScale();
|
||||
}
|
||||
@@ -545,7 +545,7 @@ love::graphics::Shader *Graphics::getShader() const
|
||||
|
||||
void Graphics::setCanvas(RenderTarget rt, uint32 temporaryRTFlags)
|
||||
{
|
||||
if (rt.canvas == nullptr)
|
||||
if (rt.texture == nullptr)
|
||||
return setCanvas();
|
||||
|
||||
RenderTargets rts;
|
||||
@@ -561,9 +561,9 @@ void Graphics::setCanvas(const RenderTargetsStrongRef &rts)
|
||||
targets.colors.reserve(rts.colors.size());
|
||||
|
||||
for (const auto &rt : rts.colors)
|
||||
targets.colors.emplace_back(rt.canvas.get(), rt.slice, rt.mipmap);
|
||||
targets.colors.emplace_back(rt.texture.get(), rt.slice, rt.mipmap);
|
||||
|
||||
targets.depthStencil = RenderTarget(rts.depthStencil.canvas, rts.depthStencil.slice, rts.depthStencil.mipmap);
|
||||
targets.depthStencil = RenderTarget(rts.depthStencil.texture, rts.depthStencil.slice, rts.depthStencil.mipmap);
|
||||
targets.temporaryRTFlags = rts.temporaryRTFlags;
|
||||
|
||||
return setCanvas(targets);
|
||||
@@ -575,9 +575,9 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
int ncanvases = (int) rts.colors.size();
|
||||
|
||||
RenderTarget firsttarget = rts.getFirstTarget();
|
||||
love::graphics::Canvas *firstcanvas = firsttarget.canvas;
|
||||
Texture *firsttex = firsttarget.texture;
|
||||
|
||||
if (firstcanvas == nullptr)
|
||||
if (firsttex == nullptr)
|
||||
return setCanvas();
|
||||
|
||||
const auto &prevRTs = state.renderTargets;
|
||||
@@ -612,29 +612,35 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
|
||||
PixelFormat firstcolorformat = PIXELFORMAT_UNKNOWN;
|
||||
if (!rts.colors.empty())
|
||||
firstcolorformat = rts.colors[0].canvas->getPixelFormat();
|
||||
firstcolorformat = rts.colors[0].texture->getPixelFormat();
|
||||
|
||||
if (!firsttex->isRenderTarget())
|
||||
throw love::Exception("Texture must be created as a render target to be used in setCanvas.");
|
||||
|
||||
if (isPixelFormatDepthStencil(firstcolorformat))
|
||||
throw love::Exception("Depth/stencil format Canvases must be used with the 'depthstencil' field of the table passed into setCanvas.");
|
||||
|
||||
if (firsttarget.mipmap < 0 || firsttarget.mipmap >= firstcanvas->getMipmapCount())
|
||||
if (firsttarget.mipmap < 0 || firsttarget.mipmap >= firsttex->getMipmapCount())
|
||||
throw love::Exception("Invalid mipmap level %d.", firsttarget.mipmap + 1);
|
||||
|
||||
if (!firstcanvas->isValidSlice(firsttarget.slice))
|
||||
if (!firsttex->isValidSlice(firsttarget.slice))
|
||||
throw love::Exception("Invalid slice index: %d.", firsttarget.slice + 1);
|
||||
|
||||
bool hasSRGBcanvas = firstcolorformat == PIXELFORMAT_sRGBA8_UNORM;
|
||||
int pixelw = firstcanvas->getPixelWidth(firsttarget.mipmap);
|
||||
int pixelh = firstcanvas->getPixelHeight(firsttarget.mipmap);
|
||||
int reqmsaa = firstcanvas->getRequestedMSAA();
|
||||
int pixelw = firsttex->getPixelWidth(firsttarget.mipmap);
|
||||
int pixelh = firsttex->getPixelHeight(firsttarget.mipmap);
|
||||
int reqmsaa = firsttex->getRequestedMSAA();
|
||||
|
||||
for (int i = 1; i < ncanvases; i++)
|
||||
{
|
||||
love::graphics::Canvas *c = rts.colors[i].canvas;
|
||||
Texture *c = rts.colors[i].texture;
|
||||
PixelFormat format = c->getPixelFormat();
|
||||
int mip = rts.colors[i].mipmap;
|
||||
int slice = rts.colors[i].slice;
|
||||
|
||||
if (!c->isRenderTarget())
|
||||
throw love::Exception("Texture must be created as a render target to be used in setCanvas.");
|
||||
|
||||
if (mip < 0 || mip >= c->getMipmapCount())
|
||||
throw love::Exception("Invalid mipmap level %d.", mip + 1);
|
||||
|
||||
@@ -657,20 +663,23 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
hasSRGBcanvas = true;
|
||||
}
|
||||
|
||||
if (rts.depthStencil.canvas != nullptr)
|
||||
if (rts.depthStencil.texture != nullptr)
|
||||
{
|
||||
love::graphics::Canvas *c = rts.depthStencil.canvas;
|
||||
Texture *c = rts.depthStencil.texture;
|
||||
int mip = rts.depthStencil.mipmap;
|
||||
int slice = rts.depthStencil.slice;
|
||||
|
||||
if (!c->isRenderTarget())
|
||||
throw love::Exception("Texture must be created as a render target to be used in setCanvas.");
|
||||
|
||||
if (!isPixelFormatDepthStencil(c->getPixelFormat()))
|
||||
throw love::Exception("Only depth/stencil format Canvases can be used with the 'depthstencil' field of the table passed into setCanvas.");
|
||||
throw love::Exception("Only depth/stencil format Texture can be used with the 'depthstencil' field of the table passed into setCanvas.");
|
||||
|
||||
if (c->getPixelWidth(mip) != pixelw || c->getPixelHeight(mip) != pixelh)
|
||||
throw love::Exception("All canvases must have the same pixel dimensions.");
|
||||
throw love::Exception("All Textures must have the same pixel dimensions.");
|
||||
|
||||
if (c->getRequestedMSAA() != firstcanvas->getRequestedMSAA())
|
||||
throw love::Exception("All Canvases must have the same MSAA value.");
|
||||
if (c->getRequestedMSAA() != firsttex->getRequestedMSAA())
|
||||
throw love::Exception("All Textures must have the same MSAA value.");
|
||||
|
||||
if (mip < 0 || mip >= c->getMipmapCount())
|
||||
throw love::Exception("Invalid mipmap level %d.", mip + 1);
|
||||
@@ -679,12 +688,12 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
throw love::Exception("Invalid slice index: %d.", slice + 1);
|
||||
}
|
||||
|
||||
int w = firstcanvas->getWidth(firsttarget.mipmap);
|
||||
int h = firstcanvas->getHeight(firsttarget.mipmap);
|
||||
int w = firsttex->getWidth(firsttarget.mipmap);
|
||||
int h = firsttex->getHeight(firsttarget.mipmap);
|
||||
|
||||
flushStreamDraws();
|
||||
|
||||
if (rts.depthStencil.canvas == nullptr && rts.temporaryRTFlags != 0)
|
||||
if (rts.depthStencil.texture == nullptr && rts.temporaryRTFlags != 0)
|
||||
{
|
||||
bool wantsdepth = (rts.temporaryRTFlags & TEMPORARY_RT_DEPTH) != 0;
|
||||
bool wantsstencil = (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) != 0;
|
||||
@@ -703,7 +712,7 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
// we don't want to directly store it in the main graphics state.
|
||||
RenderTargets realRTs = rts;
|
||||
|
||||
realRTs.depthStencil.canvas = getTemporaryCanvas(dsformat, pixelw, pixelh, reqmsaa);
|
||||
realRTs.depthStencil.texture = getTemporaryTexture(dsformat, pixelw, pixelh, reqmsaa);
|
||||
realRTs.depthStencil.slice = 0;
|
||||
|
||||
setCanvasInternal(realRTs, w, h, pixelw, pixelh, hasSRGBcanvas);
|
||||
@@ -715,28 +724,28 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
refs.colors.reserve(rts.colors.size());
|
||||
|
||||
for (auto c : rts.colors)
|
||||
refs.colors.emplace_back(c.canvas, c.slice, c.mipmap);
|
||||
refs.colors.emplace_back(c.texture, c.slice, c.mipmap);
|
||||
|
||||
refs.depthStencil = RenderTargetStrongRef(rts.depthStencil.canvas, rts.depthStencil.slice);
|
||||
refs.depthStencil = RenderTargetStrongRef(rts.depthStencil.texture, rts.depthStencil.slice);
|
||||
refs.temporaryRTFlags = rts.temporaryRTFlags;
|
||||
|
||||
std::swap(state.renderTargets, refs);
|
||||
|
||||
canvasSwitchCount++;
|
||||
renderTargetSwitchCount++;
|
||||
}
|
||||
|
||||
void Graphics::setCanvas()
|
||||
{
|
||||
DisplayState &state = states.back();
|
||||
|
||||
if (state.renderTargets.colors.empty() && state.renderTargets.depthStencil.canvas == nullptr)
|
||||
if (state.renderTargets.colors.empty() && state.renderTargets.depthStencil.texture == nullptr)
|
||||
return;
|
||||
|
||||
flushStreamDraws();
|
||||
setCanvasInternal(RenderTargets(), width, height, pixelWidth, pixelHeight, isGammaCorrect());
|
||||
|
||||
state.renderTargets = RenderTargetsStrongRef();
|
||||
canvasSwitchCount++;
|
||||
renderTargetSwitchCount++;
|
||||
}
|
||||
|
||||
Graphics::RenderTargets Graphics::getCanvas() const
|
||||
@@ -747,9 +756,9 @@ Graphics::RenderTargets Graphics::getCanvas() const
|
||||
rts.colors.reserve(curRTs.colors.size());
|
||||
|
||||
for (const auto &rt : curRTs.colors)
|
||||
rts.colors.emplace_back(rt.canvas.get(), rt.slice, rt.mipmap);
|
||||
rts.colors.emplace_back(rt.texture.get(), rt.slice, rt.mipmap);
|
||||
|
||||
rts.depthStencil = RenderTarget(curRTs.depthStencil.canvas, curRTs.depthStencil.slice, curRTs.depthStencil.mipmap);
|
||||
rts.depthStencil = RenderTarget(curRTs.depthStencil.texture, curRTs.depthStencil.slice, curRTs.depthStencil.mipmap);
|
||||
rts.temporaryRTFlags = curRTs.temporaryRTFlags;
|
||||
|
||||
return rts;
|
||||
@@ -758,7 +767,7 @@ Graphics::RenderTargets Graphics::getCanvas() const
|
||||
bool Graphics::isCanvasActive() const
|
||||
{
|
||||
const auto &rts = states.back().renderTargets;
|
||||
return !rts.colors.empty() || rts.depthStencil.canvas != nullptr;
|
||||
return !rts.colors.empty() || rts.depthStencil.texture != nullptr;
|
||||
}
|
||||
|
||||
bool Graphics::isRenderTargetActive(Texture *texture) const
|
||||
@@ -767,11 +776,11 @@ bool Graphics::isRenderTargetActive(Texture *texture) const
|
||||
|
||||
for (const auto &rt : rts.colors)
|
||||
{
|
||||
if (rt.canvas.get() == texture)
|
||||
if (rt.texture.get() == texture)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rts.depthStencil.canvas.get() == texture)
|
||||
if (rts.depthStencil.texture.get() == texture)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -783,33 +792,33 @@ bool Graphics::isRenderTargetActive(Texture *texture, int slice) const
|
||||
|
||||
for (const auto &rt : rts.colors)
|
||||
{
|
||||
if (rt.canvas.get() == texture && rt.slice == slice)
|
||||
if (rt.texture.get() == texture && rt.slice == slice)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rts.depthStencil.canvas.get() == texture && rts.depthStencil.slice == slice)
|
||||
if (rts.depthStencil.texture.get() == texture && rts.depthStencil.slice == slice)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Canvas *Graphics::getTemporaryCanvas(PixelFormat format, int w, int h, int samples)
|
||||
Texture *Graphics::getTemporaryTexture(PixelFormat format, int w, int h, int samples)
|
||||
{
|
||||
love::graphics::Canvas *canvas = nullptr;
|
||||
Texture *texture = nullptr;
|
||||
|
||||
for (TemporaryCanvas &temp : temporaryCanvases)
|
||||
for (TemporaryTexture &temp : temporaryTextures)
|
||||
{
|
||||
Canvas *c = temp.canvas;
|
||||
Texture *c = temp.texture;
|
||||
if (c->getPixelFormat() == format && c->getPixelWidth() == w
|
||||
&& c->getPixelHeight() == h && c->getRequestedMSAA() == samples)
|
||||
{
|
||||
canvas = c;
|
||||
texture = c;
|
||||
temp.framesSinceUse = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (canvas == nullptr)
|
||||
if (texture == nullptr)
|
||||
{
|
||||
Canvas::Settings settings;
|
||||
settings.format = format;
|
||||
@@ -817,12 +826,12 @@ Canvas *Graphics::getTemporaryCanvas(PixelFormat format, int w, int h, int sampl
|
||||
settings.height = h;
|
||||
settings.msaa = samples;
|
||||
|
||||
canvas = newCanvas(settings);
|
||||
texture = newCanvas(settings);
|
||||
|
||||
temporaryCanvases.emplace_back(canvas);
|
||||
temporaryTextures.emplace_back(texture);
|
||||
}
|
||||
|
||||
return canvas;
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Graphics::intersectScissor(const Rect &rect)
|
||||
@@ -1591,7 +1600,7 @@ Graphics::Stats Graphics::getStats() const
|
||||
if (streamBufferState.vertexCount > 0)
|
||||
stats.drawCalls++;
|
||||
|
||||
stats.canvasSwitches = canvasSwitchCount;
|
||||
stats.renderTargetSwitches = renderTargetSwitchCount;
|
||||
stats.drawCallsBatched = drawCallsBatched;
|
||||
stats.textures = Texture::textureCount;
|
||||
stats.fonts = Font::fontCount;
|
||||
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
{
|
||||
int drawCalls;
|
||||
int drawCallsBatched;
|
||||
int canvasSwitches;
|
||||
int renderTargetSwitches;
|
||||
int shaderSwitches;
|
||||
int textures;
|
||||
int fonts;
|
||||
@@ -315,53 +315,53 @@ public:
|
||||
|
||||
struct RenderTarget
|
||||
{
|
||||
Canvas *canvas;
|
||||
Texture *texture;
|
||||
int slice;
|
||||
int mipmap;
|
||||
|
||||
RenderTarget(Canvas *canvas, int slice = 0, int mipmap = 0)
|
||||
: canvas(canvas)
|
||||
RenderTarget(Texture *texture, int slice = 0, int mipmap = 0)
|
||||
: texture(texture)
|
||||
, slice(slice)
|
||||
, mipmap(mipmap)
|
||||
{}
|
||||
|
||||
RenderTarget()
|
||||
: canvas(nullptr)
|
||||
: texture(nullptr)
|
||||
, slice(0)
|
||||
, mipmap(0)
|
||||
{}
|
||||
|
||||
bool operator != (const RenderTarget &other) const
|
||||
{
|
||||
return canvas != other.canvas || slice != other.slice || mipmap != other.mipmap;
|
||||
return texture != other.texture || slice != other.slice || mipmap != other.mipmap;
|
||||
}
|
||||
|
||||
bool operator != (const RenderTargetStrongRef &other) const
|
||||
{
|
||||
return canvas != other.canvas.get() || slice != other.slice || mipmap != other.mipmap;
|
||||
return texture != other.texture.get() || slice != other.slice || mipmap != other.mipmap;
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderTargetStrongRef
|
||||
{
|
||||
StrongRef<Canvas> canvas;
|
||||
StrongRef<Texture> texture;
|
||||
int slice = 0;
|
||||
int mipmap = 0;
|
||||
|
||||
RenderTargetStrongRef(Canvas *canvas, int slice = 0, int mipmap = 0)
|
||||
: canvas(canvas)
|
||||
RenderTargetStrongRef(Texture *texture, int slice = 0, int mipmap = 0)
|
||||
: texture(texture)
|
||||
, slice(slice)
|
||||
, mipmap(mipmap)
|
||||
{}
|
||||
|
||||
bool operator != (const RenderTargetStrongRef &other) const
|
||||
{
|
||||
return canvas.get() != other.canvas.get() || slice != other.slice || mipmap != other.mipmap;
|
||||
return texture.get() != other.texture.get() || slice != other.slice || mipmap != other.mipmap;
|
||||
}
|
||||
|
||||
bool operator != (const RenderTarget &other) const
|
||||
{
|
||||
return canvas.get() != other.canvas || slice != other.slice || mipmap != other.mipmap;
|
||||
return texture.get() != other.texture || slice != other.slice || mipmap != other.mipmap;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -619,12 +619,12 @@ public:
|
||||
const BlendState &getBlendState() const;
|
||||
|
||||
/**
|
||||
* Sets the default sampler state for images, canvases, and fonts.
|
||||
* Sets the default sampler state for textures, videos, and fonts.
|
||||
**/
|
||||
void setDefaultSamplerState(const SamplerState &s);
|
||||
|
||||
/**
|
||||
* Gets the default sampler state for images, canvases, and fonts.
|
||||
* Gets the default sampler state for textures, videos, and fonts.
|
||||
**/
|
||||
const SamplerState &getDefaultSamplerState() const;
|
||||
|
||||
@@ -939,13 +939,13 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
struct TemporaryCanvas
|
||||
struct TemporaryTexture
|
||||
{
|
||||
Canvas *canvas;
|
||||
Texture *texture;
|
||||
int framesSinceUse;
|
||||
|
||||
TemporaryCanvas(Canvas *c)
|
||||
: canvas(c)
|
||||
TemporaryTexture(Texture *tex)
|
||||
: texture(tex)
|
||||
, framesSinceUse(0)
|
||||
{}
|
||||
};
|
||||
@@ -961,7 +961,7 @@ protected:
|
||||
|
||||
void createQuadIndexBuffer();
|
||||
|
||||
Canvas *getTemporaryCanvas(PixelFormat format, int w, int h, int samples);
|
||||
Texture *getTemporaryTexture(PixelFormat format, int w, int h, int samples);
|
||||
|
||||
void restoreState(const DisplayState &s);
|
||||
void restoreStateChecked(const DisplayState &s);
|
||||
@@ -994,9 +994,9 @@ protected:
|
||||
std::vector<DisplayState> states;
|
||||
std::vector<StackType> stackTypeStack;
|
||||
|
||||
std::vector<TemporaryCanvas> temporaryCanvases;
|
||||
std::vector<TemporaryTexture> temporaryTextures;
|
||||
|
||||
int canvasSwitchCount;
|
||||
int renderTargetSwitchCount;
|
||||
int drawCalls;
|
||||
int drawCallsBatched;
|
||||
|
||||
@@ -1007,7 +1007,7 @@ protected:
|
||||
Deprecations deprecations;
|
||||
|
||||
static const size_t MAX_USER_STACK_DEPTH = 128;
|
||||
static const int MAX_TEMPORARY_CANVAS_UNUSED_FRAMES = 16;
|
||||
static const int MAX_TEMPORARY_TEXTURE_UNUSED_FRAMES = 16;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -31,20 +31,17 @@ namespace graphics
|
||||
|
||||
love::Type Image::type("Image", &Texture::type);
|
||||
|
||||
Image::Image(const Slices &data, const Settings &settings, bool validatedata)
|
||||
: Texture(data.getTextureType())
|
||||
Image::Image(TextureType textype, const Settings &settings)
|
||||
: Texture(textype)
|
||||
, settings(settings)
|
||||
, mipmapsType(settings.mipmaps ? MIPMAPS_GENERATED : MIPMAPS_NONE)
|
||||
, usingDefaultTexture(false)
|
||||
{
|
||||
renderTarget = false;
|
||||
sRGB = isGammaCorrect() && !settings.linear;
|
||||
if (validatedata && data.validate() && data.getMipmapCount() > 1)
|
||||
mipmapsType = MIPMAPS_DATA;
|
||||
}
|
||||
|
||||
Image::Image(TextureType textype, PixelFormat format, int width, int height, int slices, const Settings &settings)
|
||||
: Image(Slices(textype), settings, false)
|
||||
: Image(textype, settings)
|
||||
{
|
||||
if (isPixelFormatCompressed(format))
|
||||
throw love::Exception("This constructor is only supported for non-compressed pixel formats.");
|
||||
@@ -54,26 +51,30 @@ Image::Image(TextureType textype, PixelFormat format, int width, int height, int
|
||||
else if (textype == TEXTURE_VOLUME)
|
||||
depth = slices;
|
||||
|
||||
init(format, width, height, settings);
|
||||
init(format, width, height, 1, settings);
|
||||
}
|
||||
|
||||
Image::Image(const Slices &slices, const Settings &settings)
|
||||
: Image(slices, settings, true)
|
||||
: Image(slices.getTextureType(), settings)
|
||||
{
|
||||
int dataMipmaps = 1;
|
||||
if (slices.validate() && slices.getMipmapCount() > 1)
|
||||
dataMipmaps = slices.getMipmapCount();
|
||||
|
||||
if (texType == TEXTURE_2D_ARRAY)
|
||||
this->layers = slices.getSliceCount();
|
||||
else if (texType == TEXTURE_VOLUME)
|
||||
this->depth = slices.getSliceCount();
|
||||
|
||||
love::image::ImageDataBase *slice = slices.get(0, 0);
|
||||
init(slice->getFormat(), slice->getWidth(), slice->getHeight(), settings);
|
||||
init(slice->getFormat(), slice->getWidth(), slice->getHeight(), dataMipmaps, settings);
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
}
|
||||
|
||||
void Image::init(PixelFormat fmt, int w, int h, const Settings &settings)
|
||||
void Image::init(PixelFormat fmt, int w, int h, int dataMipmaps, const Settings &settings)
|
||||
{
|
||||
Graphics *gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr && !gfx->isPixelFormatSupported(fmt, renderTarget, readable, sRGB))
|
||||
@@ -96,10 +97,10 @@ void Image::init(PixelFormat fmt, int w, int h, const Settings &settings)
|
||||
|
||||
format = fmt;
|
||||
|
||||
if (isCompressed() && mipmapsType == MIPMAPS_GENERATED)
|
||||
mipmapsType = MIPMAPS_NONE;
|
||||
|
||||
mipmapCount = mipmapsType == MIPMAPS_NONE ? 1 : getTotalMipmapCount(w, h, depth);
|
||||
if (!settings.mipmaps || (isCompressed() && dataMipmaps <= 1))
|
||||
mipmapCount = 1;
|
||||
else
|
||||
mipmapCount = getTotalMipmapCount(w, h, depth);
|
||||
|
||||
initQuad();
|
||||
}
|
||||
@@ -125,7 +126,7 @@ void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap,
|
||||
if (d->getFormat() != getPixelFormat())
|
||||
throw love::Exception("Pixel formats must match.");
|
||||
|
||||
if (mipmap < 0 || (mipmapsType != MIPMAPS_DATA && mipmap > 0) || mipmap >= getMipmapCount())
|
||||
if (mipmap < 0 || mipmap >= getMipmapCount())
|
||||
throw love::Exception("Invalid image mipmap index %d.", mipmap + 1);
|
||||
|
||||
if (slice < 0 || (texType == TEXTURE_CUBE && slice >= 6)
|
||||
@@ -168,11 +169,6 @@ void Image::replacePixels(const void *data, size_t size, int slice, int mipmap,
|
||||
generateMipmaps();
|
||||
}
|
||||
|
||||
Image::MipmapsType Image::getMipmapsType() const
|
||||
{
|
||||
return mipmapsType;
|
||||
}
|
||||
|
||||
bool Image::getConstant(const char *in, SettingType &out)
|
||||
{
|
||||
return settingTypes.find(in, out);
|
||||
|
||||
@@ -57,8 +57,6 @@ public:
|
||||
void replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, int x, int y, bool reloadmipmaps);
|
||||
void replacePixels(const void *data, size_t size, int slice, int mipmap, const Rect &rect, bool reloadmipmaps);
|
||||
|
||||
MipmapsType getMipmapsType() const;
|
||||
|
||||
static bool getConstant(const char *in, SettingType &out);
|
||||
static bool getConstant(SettingType in, const char *&out);
|
||||
static const char *getConstant(SettingType in);
|
||||
@@ -75,17 +73,15 @@ protected:
|
||||
// The settings used to initialize this Image.
|
||||
Settings settings;
|
||||
|
||||
MipmapsType mipmapsType;
|
||||
|
||||
// True if the image wasn't able to be properly created and it had to fall
|
||||
// back to a default texture.
|
||||
bool usingDefaultTexture;
|
||||
|
||||
private:
|
||||
|
||||
Image(const Slices &data, const Settings &settings, bool validatedata);
|
||||
Image(TextureType textype, const Settings &settings);
|
||||
|
||||
void init(PixelFormat fmt, int w, int h, const Settings &settings);
|
||||
void init(PixelFormat fmt, int w, int h, int dataMipmaps, const Settings &settings);
|
||||
|
||||
static StringMap<SettingType, SETTING_MAX_ENUM>::Entry settingTypeEntries[];
|
||||
static StringMap<SettingType, SETTING_MAX_ENUM> settingTypes;
|
||||
|
||||
@@ -680,5 +680,29 @@ StringMap<TextureType, TEXTURE_MAX_ENUM>::Entry Texture::texTypeEntries[] =
|
||||
|
||||
StringMap<TextureType, TEXTURE_MAX_ENUM> Texture::texTypes(Texture::texTypeEntries, sizeof(Texture::texTypeEntries));
|
||||
|
||||
static StringMap<Texture::MipmapsMode, Texture::MIPMAPS_MAX_ENUM>::Entry mipmapEntries[] =
|
||||
{
|
||||
{ "none", Texture::MIPMAPS_NONE },
|
||||
{ "manual", Texture::MIPMAPS_MANUAL },
|
||||
{ "auto", Texture::MIPMAPS_AUTO },
|
||||
};
|
||||
|
||||
static StringMap<Texture::MipmapsMode, Texture::MIPMAPS_MAX_ENUM> mipmapModes(mipmapEntries, sizeof(mipmapEntries));
|
||||
|
||||
bool Texture::getConstant(const char *in, MipmapsMode &out)
|
||||
{
|
||||
return mipmapModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Texture::getConstant(MipmapsMode in, const char *&out)
|
||||
{
|
||||
return mipmapModes.find(in, out);
|
||||
}
|
||||
|
||||
std::vector<std::string> Texture::getConstants(MipmapsMode)
|
||||
{
|
||||
return mipmapModes.getNames();
|
||||
}
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -128,11 +128,12 @@ public:
|
||||
static love::Type type;
|
||||
static int textureCount;
|
||||
|
||||
enum MipmapsType
|
||||
enum MipmapsMode
|
||||
{
|
||||
MIPMAPS_NONE,
|
||||
MIPMAPS_DATA,
|
||||
MIPMAPS_GENERATED,
|
||||
MIPMAPS_MANUAL,
|
||||
MIPMAPS_AUTO,
|
||||
MIPMAPS_MAX_ENUM
|
||||
};
|
||||
|
||||
struct Slices
|
||||
@@ -222,6 +223,10 @@ public:
|
||||
static bool getConstant(TextureType in, const char *&out);
|
||||
static std::vector<std::string> getConstants(TextureType);
|
||||
|
||||
static bool getConstant(const char *in, MipmapsMode &out);
|
||||
static bool getConstant(MipmapsMode in, const char *&out);
|
||||
static std::vector<std::string> getConstants(MipmapsMode);
|
||||
|
||||
protected:
|
||||
|
||||
void initQuad();
|
||||
|
||||
@@ -373,8 +373,11 @@ love::image::ImageData *Canvas::newImageData(love::image::Image *module, int sli
|
||||
|
||||
void Canvas::generateMipmaps()
|
||||
{
|
||||
if (getMipmapCount() == 1 || getMipmapMode() == MIPMAPS_NONE)
|
||||
throw love::Exception("generateMipmaps can only be called on a Canvas which was created with mipmaps enabled.");
|
||||
if (getMipmapCount() == 1 || getMipmapsMode() == MIPMAPS_NONE)
|
||||
throw love::Exception("generateMipmaps can only be called on a Texture which was created with mipmaps enabled.");
|
||||
|
||||
if (isPixelFormatCompressed(format))
|
||||
throw love::Exception("generateMipmaps cannot be called on a compressed Texture.");
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
|
||||
// Set whether drawing converts input from linear -> sRGB colorspace.
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB
|
||||
|| GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB)
|
||||
|| GLAD_ES_VERSION_3_0)
|
||||
{
|
||||
if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control)
|
||||
gl.setEnableState(OpenGL::ENABLE_FRAMEBUFFER_SRGB, isGammaCorrect());
|
||||
@@ -312,11 +312,11 @@ void Graphics::unSetMode()
|
||||
for (const auto &pair : framebufferObjects)
|
||||
gl.deleteFramebuffer(pair.second);
|
||||
|
||||
for (auto temp : temporaryCanvases)
|
||||
temp.canvas->release();
|
||||
for (auto temp : temporaryTextures)
|
||||
temp.texture->release();
|
||||
|
||||
framebufferObjects.clear();
|
||||
temporaryCanvases.clear();
|
||||
temporaryTextures.clear();
|
||||
|
||||
if (mainVAO != 0)
|
||||
{
|
||||
@@ -518,7 +518,7 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix
|
||||
flushStreamDraws();
|
||||
endPass();
|
||||
|
||||
bool iswindow = rts.getFirstTarget().canvas == nullptr;
|
||||
bool iswindow = rts.getFirstTarget().texture == nullptr;
|
||||
vertex::Winding vertexwinding = state.winding;
|
||||
|
||||
if (iswindow)
|
||||
@@ -560,7 +560,7 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix
|
||||
void Graphics::endPass()
|
||||
{
|
||||
auto &rts = states.back().renderTargets;
|
||||
love::graphics::Canvas *depthstencil = rts.depthStencil.canvas.get();
|
||||
love::graphics::Texture *depthstencil = rts.depthStencil.texture.get();
|
||||
|
||||
// Discard the depth/stencil buffer if we're using an internal cached one.
|
||||
if (depthstencil == nullptr && (rts.temporaryRTFlags & (TEMPORARY_RT_DEPTH | TEMPORARY_RT_STENCIL)) != 0)
|
||||
@@ -568,15 +568,16 @@ void Graphics::endPass()
|
||||
|
||||
// Resolve MSAA buffers. MSAA is only supported for 2D render targets so we
|
||||
// don't have to worry about resolving to slices.
|
||||
if (rts.colors.size() > 0 && rts.colors[0].canvas->getMSAA() > 1)
|
||||
if (rts.colors.size() > 0 && rts.colors[0].texture->getMSAA() > 1)
|
||||
{
|
||||
int mip = rts.colors[0].mipmap;
|
||||
int w = rts.colors[0].canvas->getPixelWidth(mip);
|
||||
int h = rts.colors[0].canvas->getPixelHeight(mip);
|
||||
int w = rts.colors[0].texture->getPixelWidth(mip);
|
||||
int h = rts.colors[0].texture->getPixelHeight(mip);
|
||||
|
||||
for (int i = 0; i < (int) rts.colors.size(); i++)
|
||||
{
|
||||
Canvas *c = (Canvas *) rts.colors[i].canvas.get();
|
||||
// FIXME
|
||||
Canvas *c = (Canvas *) rts.colors[i].texture.get();
|
||||
|
||||
if (!c->isReadable())
|
||||
continue;
|
||||
@@ -619,13 +620,14 @@ void Graphics::endPass()
|
||||
|
||||
for (const auto &rt : rts.colors)
|
||||
{
|
||||
if (rt.canvas->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0)
|
||||
rt.canvas->generateMipmaps();
|
||||
// TODO
|
||||
// if (rt.texture->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0)
|
||||
// rt.texture->generateMipmaps();
|
||||
}
|
||||
|
||||
int dsmipmap = rts.depthStencil.mipmap;
|
||||
if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAPS_AUTO && dsmipmap == 0)
|
||||
depthstencil->generateMipmaps();
|
||||
// int dsmipmap = rts.depthStencil.mipmap;
|
||||
// if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAPS_AUTO && dsmipmap == 0)
|
||||
// depthstencil->generateMipmaps();
|
||||
}
|
||||
|
||||
void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth)
|
||||
@@ -818,25 +820,28 @@ void Graphics::discard(OpenGL::FramebufferTarget target, const std::vector<bool>
|
||||
glDiscardFramebufferEXT(gltarget, (GLint) attachments.size(), &attachments[0]);
|
||||
}
|
||||
|
||||
void Graphics::cleanupCanvas(Canvas *canvas)
|
||||
void Graphics::cleanupCanvas(Canvas *texture)
|
||||
{
|
||||
if (!texture->isRenderTarget())
|
||||
return;
|
||||
|
||||
for (auto it = framebufferObjects.begin(); it != framebufferObjects.end(); /**/)
|
||||
{
|
||||
bool hascanvas = false;
|
||||
bool hastexture = false;
|
||||
const auto &rts = it->first;
|
||||
|
||||
for (const RenderTarget &rt : rts.colors)
|
||||
{
|
||||
if (rt.canvas == canvas)
|
||||
if (rt.texture == texture)
|
||||
{
|
||||
hascanvas = true;
|
||||
hastexture = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hascanvas = hascanvas || rts.depthStencil.canvas == canvas;
|
||||
hastexture = hastexture || rts.depthStencil.texture == texture;
|
||||
|
||||
if (hascanvas)
|
||||
if (hastexture)
|
||||
{
|
||||
if (isCreated())
|
||||
gl.deleteFramebuffer(it->second);
|
||||
@@ -857,8 +862,8 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
}
|
||||
else
|
||||
{
|
||||
int msaa = targets.getFirstTarget().canvas->getMSAA();
|
||||
bool hasDS = targets.depthStencil.canvas != nullptr;
|
||||
int msaa = targets.getFirstTarget().texture->getMSAA();
|
||||
bool hasDS = targets.depthStencil.texture != nullptr;
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, fbo);
|
||||
@@ -868,9 +873,9 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
|
||||
auto attachCanvas = [&](const RenderTarget &rt)
|
||||
{
|
||||
bool renderbuffer = msaa > 1 || !rt.canvas->isReadable();
|
||||
bool renderbuffer = msaa > 1 || !rt.texture->isReadable();
|
||||
bool srgb = false;
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.canvas->getPixelFormat(), renderbuffer, srgb);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer, srgb);
|
||||
|
||||
if (fmt.framebufferAttachments[0] == GL_COLOR_ATTACHMENT0)
|
||||
{
|
||||
@@ -879,7 +884,7 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
ncolortargets++;
|
||||
}
|
||||
|
||||
GLuint handle = (GLuint) rt.canvas->getRenderTargetHandle();
|
||||
GLuint handle = (GLuint) rt.texture->getRenderTargetHandle();
|
||||
|
||||
for (GLenum attachment : fmt.framebufferAttachments)
|
||||
{
|
||||
@@ -889,7 +894,7 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, handle);
|
||||
else
|
||||
{
|
||||
TextureType textype = rt.canvas->getTextureType();
|
||||
TextureType textype = rt.texture->getTextureType();
|
||||
|
||||
int layer = textype == TEXTURE_CUBE ? 0 : rt.slice;
|
||||
int face = textype == TEXTURE_CUBE ? rt.slice : 0;
|
||||
@@ -1056,20 +1061,20 @@ void Graphics::present(void *screenshotCallbackData)
|
||||
// Reset the per-frame stat counts.
|
||||
drawCalls = 0;
|
||||
gl.stats.shaderSwitches = 0;
|
||||
canvasSwitchCount = 0;
|
||||
renderTargetSwitchCount = 0;
|
||||
drawCallsBatched = 0;
|
||||
|
||||
// This assumes temporary canvases will only be used within a render pass.
|
||||
for (int i = (int) temporaryCanvases.size() - 1; i >= 0; i--)
|
||||
// This assumes temporary textures will only be used within a render pass.
|
||||
for (int i = (int) temporaryTextures.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (temporaryCanvases[i].framesSinceUse >= MAX_TEMPORARY_CANVAS_UNUSED_FRAMES)
|
||||
if (temporaryTextures[i].framesSinceUse >= MAX_TEMPORARY_TEXTURE_UNUSED_FRAMES)
|
||||
{
|
||||
temporaryCanvases[i].canvas->release();
|
||||
temporaryCanvases[i] = temporaryCanvases.back();
|
||||
temporaryCanvases.pop_back();
|
||||
temporaryTextures[i].texture->release();
|
||||
temporaryTextures[i] = temporaryTextures.back();
|
||||
temporaryTextures.pop_back();
|
||||
}
|
||||
else
|
||||
temporaryCanvases[i].framesSinceUse++;
|
||||
temporaryTextures[i].framesSinceUse++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1111,11 +1116,11 @@ void Graphics::setScissor()
|
||||
void Graphics::drawToStencilBuffer(StencilAction action, int value)
|
||||
{
|
||||
const auto &rts = states.back().renderTargets;
|
||||
love::graphics::Canvas *dscanvas = rts.depthStencil.canvas.get();
|
||||
love::graphics::Texture *dstexture = rts.depthStencil.texture.get();
|
||||
|
||||
if (!isCanvasActive() && !windowHasStencil)
|
||||
throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer.");
|
||||
else if (isCanvasActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dscanvas == nullptr || !isPixelFormatStencil(dscanvas->getPixelFormat())))
|
||||
else if (isCanvasActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dstexture == nullptr || !isPixelFormatStencil(dstexture->getPixelFormat())))
|
||||
throw love::Exception("Drawing to the stencil buffer with a Canvas active requires either stencil=true or a custom stencil-type Canvas to be used, in setCanvas.");
|
||||
|
||||
flushStreamDraws();
|
||||
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
for (size_t i = 0; i < rts.colors.size(); i++)
|
||||
hashtargets[hashcount++] = rts.colors[i];
|
||||
|
||||
if (rts.depthStencil.canvas != nullptr)
|
||||
if (rts.depthStencil.texture != nullptr)
|
||||
hashtargets[hashcount++] = rts.depthStencil;
|
||||
else if (rts.temporaryRTFlags != 0)
|
||||
hashtargets[hashcount++] = RenderTarget(nullptr, -1, rts.temporaryRTFlags);
|
||||
|
||||
@@ -148,7 +148,7 @@ void Image::loadData()
|
||||
d = std::max(d / 2, 1);
|
||||
}
|
||||
|
||||
if (mipmapsType == MIPMAPS_GENERATED)
|
||||
if (getMipmapCount() > 1 && slices.getMipmapCount() <= 1)
|
||||
generateMipmaps();
|
||||
}
|
||||
|
||||
@@ -200,22 +200,11 @@ bool Image::loadVolatile()
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Image load");
|
||||
|
||||
if (!isCompressed())
|
||||
{
|
||||
// GL_EXT_sRGB doesn't support glGenerateMipmap for sRGB textures.
|
||||
if (sRGB && (GLAD_ES_VERSION_2_0 && GLAD_EXT_sRGB && !GLAD_ES_VERSION_3_0)
|
||||
&& mipmapsType != MIPMAPS_DATA)
|
||||
{
|
||||
mipmapsType = MIPMAPS_NONE;
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// NPOT textures don't support mipmapping without full NPOT support.
|
||||
if ((GLAD_ES_VERSION_2_0 && !(GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot))
|
||||
&& (pixelWidth != nextP2(pixelWidth) || pixelHeight != nextP2(pixelHeight)))
|
||||
{
|
||||
mipmapsType = MIPMAPS_NONE;
|
||||
mipmapCount = 1;
|
||||
samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE;
|
||||
}
|
||||
|
||||
@@ -231,11 +220,6 @@ bool Image::loadVolatile()
|
||||
|
||||
setSamplerState(samplerState);
|
||||
|
||||
GLenum gltextype = OpenGL::getGLTextureType(texType);
|
||||
|
||||
if (mipmapsType == MIPMAPS_NONE && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0))
|
||||
glTexParameteri(gltextype, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
while (glGetError() != GL_NO_ERROR); // Clear errors.
|
||||
|
||||
try
|
||||
|
||||
@@ -1794,10 +1794,10 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget,
|
||||
&& (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB));
|
||||
}
|
||||
else
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB;
|
||||
return GLAD_ES_VERSION_3_0;
|
||||
}
|
||||
else
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB;
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB;
|
||||
case PIXELFORMAT_R16_UNORM:
|
||||
case PIXELFORMAT_RG16_UNORM:
|
||||
return GLAD_VERSION_3_0
|
||||
|
||||
@@ -37,7 +37,7 @@ int w_Canvas_renderTo(lua_State *L)
|
||||
|
||||
int startidx = 2;
|
||||
|
||||
if (rt.canvas->getTextureType() != TEXTURE_2D)
|
||||
if (rt.texture->getTextureType() != TEXTURE_2D)
|
||||
{
|
||||
rt.slice = (int) luaL_checkinteger(L, 2) - 1;
|
||||
startidx++;
|
||||
@@ -53,10 +53,10 @@ int w_Canvas_renderTo(lua_State *L)
|
||||
Graphics::RenderTargets oldtargets = graphics->getCanvas();
|
||||
|
||||
for (auto c : oldtargets.colors)
|
||||
c.canvas->retain();
|
||||
c.texture->retain();
|
||||
|
||||
if (oldtargets.depthStencil.canvas != nullptr)
|
||||
oldtargets.depthStencil.canvas->retain();
|
||||
if (oldtargets.depthStencil.texture != nullptr)
|
||||
oldtargets.depthStencil.texture->retain();
|
||||
|
||||
luax_catchexcept(L, [&](){ graphics->setCanvas(rt, false); });
|
||||
|
||||
@@ -66,10 +66,10 @@ int w_Canvas_renderTo(lua_State *L)
|
||||
graphics->setCanvas(oldtargets);
|
||||
|
||||
for (auto c : oldtargets.colors)
|
||||
c.canvas->release();
|
||||
c.texture->release();
|
||||
|
||||
if (oldtargets.depthStencil.canvas != nullptr)
|
||||
oldtargets.depthStencil.canvas->release();
|
||||
if (oldtargets.depthStencil.texture != nullptr)
|
||||
oldtargets.depthStencil.texture->release();
|
||||
|
||||
if (status != 0)
|
||||
return lua_error(L);
|
||||
@@ -119,8 +119,8 @@ int w_Canvas_getMipmapMode(lua_State *L)
|
||||
{
|
||||
Canvas *c = luax_checkcanvas(L, 1);
|
||||
const char *str;
|
||||
if (!Canvas::getConstant(c->getMipmapMode(), str))
|
||||
return luax_enumerror(L, "mipmap mode", Canvas::getConstants(Canvas::MIPMAPS_MAX_ENUM), str);
|
||||
if (!Texture::getConstant(c->getMipmapsMode(), str))
|
||||
return luax_enumerror(L, "mipmap mode", Texture::getConstants(Texture::MIPMAPS_MAX_ENUM), str);
|
||||
|
||||
lua_pushstring(L, str);
|
||||
return 1;
|
||||
|
||||
@@ -252,7 +252,7 @@ static Graphics::RenderTarget checkRenderTarget(lua_State *L, int idx)
|
||||
Graphics::RenderTarget target(luax_checkcanvas(L, -1), 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
TextureType type = target.canvas->getTextureType();
|
||||
TextureType type = target.texture->getTextureType();
|
||||
if (type == TEXTURE_2D_ARRAY || type == TEXTURE_VOLUME)
|
||||
target.slice = luax_checkintflag(L, idx, "layer") - 1;
|
||||
else if (type == TEXTURE_CUBE)
|
||||
@@ -294,7 +294,7 @@ int w_setCanvas(lua_State *L)
|
||||
{
|
||||
targets.colors.emplace_back(luax_checkcanvas(L, -1), 0);
|
||||
|
||||
if (targets.colors.back().canvas->getTextureType() != TEXTURE_2D)
|
||||
if (targets.colors.back().texture->getTextureType() != TEXTURE_2D)
|
||||
return luaL_error(L, "Non-2D canvases must use the table-of-tables variant of setCanvas.");
|
||||
}
|
||||
|
||||
@@ -311,13 +311,13 @@ int w_setCanvas(lua_State *L)
|
||||
else if (dstype == LUA_TBOOLEAN)
|
||||
targets.temporaryRTFlags |= luax_toboolean(L, -1) ? (tempdepthflag | tempstencilflag) : 0;
|
||||
else if (dstype != LUA_TNONE && dstype != LUA_TNIL)
|
||||
targets.depthStencil.canvas = luax_checkcanvas(L, -1);
|
||||
targets.depthStencil.texture = luax_checkcanvas(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (targets.depthStencil.canvas == nullptr && (targets.temporaryRTFlags & tempdepthflag) == 0)
|
||||
if (targets.depthStencil.texture == nullptr && (targets.temporaryRTFlags & tempdepthflag) == 0)
|
||||
targets.temporaryRTFlags |= luax_boolflag(L, 1, "depth", false) ? tempdepthflag : 0;
|
||||
|
||||
if (targets.depthStencil.canvas == nullptr && (targets.temporaryRTFlags & tempstencilflag) == 0)
|
||||
if (targets.depthStencil.texture == nullptr && (targets.temporaryRTFlags & tempstencilflag) == 0)
|
||||
targets.temporaryRTFlags |= luax_boolflag(L, 1, "stencil", false) ? tempstencilflag : 0;
|
||||
}
|
||||
else
|
||||
@@ -325,7 +325,7 @@ int w_setCanvas(lua_State *L)
|
||||
for (int i = 1; i <= lua_gettop(L); i++)
|
||||
{
|
||||
Graphics::RenderTarget target(luax_checkcanvas(L, i), 0);
|
||||
TextureType type = target.canvas->getTextureType();
|
||||
TextureType type = target.texture->getTextureType();
|
||||
|
||||
if (i == 1 && type != TEXTURE_2D)
|
||||
{
|
||||
@@ -348,7 +348,7 @@ int w_setCanvas(lua_State *L)
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&]() {
|
||||
if (targets.getFirstTarget().canvas != nullptr)
|
||||
if (targets.getFirstTarget().texture != nullptr)
|
||||
instance()->setCanvas(targets);
|
||||
else
|
||||
instance()->setCanvas();
|
||||
@@ -361,10 +361,10 @@ static void pushRenderTarget(lua_State *L, const Graphics::RenderTarget &rt)
|
||||
{
|
||||
lua_createtable(L, 1, 2);
|
||||
|
||||
luax_pushtype(L, rt.canvas);
|
||||
luax_pushtype(L, rt.texture);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
||||
TextureType type = rt.canvas->getTextureType();
|
||||
TextureType type = rt.texture->getTextureType();
|
||||
|
||||
if (type == TEXTURE_2D_ARRAY || type == TEXTURE_VOLUME)
|
||||
{
|
||||
@@ -392,13 +392,13 @@ int w_getCanvas(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool shouldUseTablesVariant = targets.depthStencil.canvas != nullptr;
|
||||
bool shouldUseTablesVariant = targets.depthStencil.texture != nullptr;
|
||||
|
||||
if (!shouldUseTablesVariant)
|
||||
{
|
||||
for (const auto &rt : targets.colors)
|
||||
{
|
||||
if (rt.mipmap != 0 || rt.canvas->getTextureType() != TEXTURE_2D)
|
||||
if (rt.mipmap != 0 || rt.texture->getTextureType() != TEXTURE_2D)
|
||||
{
|
||||
shouldUseTablesVariant = true;
|
||||
break;
|
||||
@@ -416,7 +416,7 @@ int w_getCanvas(lua_State *L)
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
if (targets.depthStencil.canvas != nullptr)
|
||||
if (targets.depthStencil.texture != nullptr)
|
||||
{
|
||||
pushRenderTarget(L, targets.depthStencil);
|
||||
lua_setfield(L, -2, "depthstencil");
|
||||
@@ -427,7 +427,7 @@ int w_getCanvas(lua_State *L)
|
||||
else
|
||||
{
|
||||
for (const auto &rt : targets.colors)
|
||||
luax_pushtype(L, rt.canvas);
|
||||
luax_pushtype(L, rt.texture);
|
||||
|
||||
return ntargets;
|
||||
}
|
||||
@@ -1240,8 +1240,8 @@ int w_newCanvas(lua_State *L)
|
||||
if (!lua_isnoneornil(L, -1))
|
||||
{
|
||||
const char *str = luaL_checkstring(L, -1);
|
||||
if (!Canvas::getConstant(str, settings.mipmaps))
|
||||
return luax_enumerror(L, "Canvas mipmap mode", Canvas::getConstants(settings.mipmaps), str);
|
||||
if (!Texture::getConstant(str, settings.mipmaps))
|
||||
return luax_enumerror(L, "Texture mipmap mode", Texture::getConstants(settings.mipmaps), str);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
@@ -2388,7 +2388,7 @@ int w_getStats(lua_State *L)
|
||||
lua_pushinteger(L, stats.drawCallsBatched);
|
||||
lua_setfield(L, -2, "drawcallsbatched");
|
||||
|
||||
lua_pushinteger(L, stats.canvasSwitches);
|
||||
lua_pushinteger(L, stats.renderTargetSwitches);
|
||||
lua_setfield(L, -2, "canvasswitches");
|
||||
|
||||
lua_pushinteger(L, stats.shaderSwitches);
|
||||
|
||||
@@ -40,7 +40,7 @@ int w_Image_replacePixels(lua_State *L)
|
||||
int mipmap = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
bool reloadmipmaps = i->getMipmapsType() == Image::MIPMAPS_GENERATED;
|
||||
bool reloadmipmaps = false; // TODO i->getMipmapsSource() == Texture::MIPMAPS_SOURCE_GENERATED;
|
||||
|
||||
if (i->getTextureType() != TEXTURE_2D)
|
||||
slice = (int) luaL_checkinteger(L, 3) - 1;
|
||||
|
||||
Reference in New Issue
Block a user