mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Move internal Slices class from Image to Texture
This commit is contained in:
@@ -429,7 +429,7 @@ public:
|
||||
// Implements Module.
|
||||
virtual ModuleType getModuleType() const { return M_GRAPHICS; }
|
||||
|
||||
virtual Image *newImage(const Image::Slices &data, const Image::Settings &settings) = 0;
|
||||
virtual Image *newImage(const Texture::Slices &data, const Image::Settings &settings) = 0;
|
||||
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);
|
||||
|
||||
@@ -40,7 +40,7 @@ Image::Image(const Slices &data, const Settings &settings, bool validatedata)
|
||||
, sRGB(isGammaCorrect() && !settings.linear)
|
||||
, usingDefaultTexture(false)
|
||||
{
|
||||
if (validatedata && data.validate() == MIPMAPS_DATA)
|
||||
if (validatedata && data.validate() && data.getMipmapCount() > 1)
|
||||
mipmapsType = MIPMAPS_DATA;
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ bool Image::isCompressed() const
|
||||
|
||||
bool Image::isFormatLinear() const
|
||||
{
|
||||
return isGammaCorrect() && !sRGB;
|
||||
return isGammaCorrect() && !sRGB && format != PIXELFORMAT_sRGBA8_UNORM;
|
||||
}
|
||||
|
||||
Image::MipmapsType Image::getMipmapsType() const
|
||||
@@ -190,168 +190,6 @@ Image::MipmapsType Image::getMipmapsType() const
|
||||
return mipmapsType;
|
||||
}
|
||||
|
||||
Image::Slices::Slices(TextureType textype)
|
||||
: textureType(textype)
|
||||
{
|
||||
}
|
||||
|
||||
void Image::Slices::clear()
|
||||
{
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void Image::Slices::set(int slice, int mipmap, love::image::ImageDataBase *d)
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
{
|
||||
if (mipmap >= (int) data.size())
|
||||
data.resize(mipmap + 1);
|
||||
|
||||
if (slice >= (int) data[mipmap].size())
|
||||
data[mipmap].resize(slice + 1);
|
||||
|
||||
data[mipmap][slice].set(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (slice >= (int) data.size())
|
||||
data.resize(slice + 1);
|
||||
|
||||
if (mipmap >= (int) data[slice].size())
|
||||
data[slice].resize(mipmap + 1);
|
||||
|
||||
data[slice][mipmap].set(d);
|
||||
}
|
||||
}
|
||||
|
||||
love::image::ImageDataBase *Image::Slices::get(int slice, int mipmap) const
|
||||
{
|
||||
if (slice < 0 || slice >= getSliceCount(mipmap))
|
||||
return nullptr;
|
||||
|
||||
if (mipmap < 0 || mipmap >= getMipmapCount(slice))
|
||||
return nullptr;
|
||||
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
return data[mipmap][slice].get();
|
||||
else
|
||||
return data[slice][mipmap].get();
|
||||
}
|
||||
|
||||
void Image::Slices::add(love::image::CompressedImageData *cdata, int startslice, int startmip, bool addallslices, bool addallmips)
|
||||
{
|
||||
int slicecount = addallslices ? cdata->getSliceCount() : 1;
|
||||
int mipcount = addallmips ? cdata->getMipmapCount() : 1;
|
||||
|
||||
for (int mip = 0; mip < mipcount; mip++)
|
||||
{
|
||||
for (int slice = 0; slice < slicecount; slice++)
|
||||
set(startslice + slice, startmip + mip, cdata->getSlice(slice, mip));
|
||||
}
|
||||
}
|
||||
|
||||
int Image::Slices::getSliceCount(int mip) const
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
{
|
||||
if (mip < 0 || mip >= (int) data.size())
|
||||
return 0;
|
||||
|
||||
return (int) data[mip].size();
|
||||
}
|
||||
else
|
||||
return (int) data.size();
|
||||
}
|
||||
|
||||
int Image::Slices::getMipmapCount(int slice) const
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
return (int) data.size();
|
||||
else
|
||||
{
|
||||
if (slice < 0 || slice >= (int) data.size())
|
||||
return 0;
|
||||
|
||||
return data[slice].size();
|
||||
}
|
||||
}
|
||||
|
||||
Image::MipmapsType Image::Slices::validate() const
|
||||
{
|
||||
int slicecount = getSliceCount();
|
||||
int mipcount = getMipmapCount(0);
|
||||
|
||||
if (slicecount == 0 || mipcount == 0)
|
||||
throw love::Exception("At least one ImageData or CompressedImageData is required!");
|
||||
|
||||
if (textureType == TEXTURE_CUBE && slicecount != 6)
|
||||
throw love::Exception("Cube textures must have exactly 6 sides.");
|
||||
|
||||
image::ImageDataBase *firstdata = get(0, 0);
|
||||
|
||||
int w = firstdata->getWidth();
|
||||
int h = firstdata->getHeight();
|
||||
int depth = textureType == TEXTURE_VOLUME ? slicecount : 1;
|
||||
PixelFormat format = firstdata->getFormat();
|
||||
|
||||
int expectedmips = Texture::getTotalMipmapCount(w, h, depth);
|
||||
|
||||
if (mipcount != expectedmips && mipcount != 1)
|
||||
throw love::Exception("Image does not have all required mipmap levels (expected %d, got %d)", expectedmips, mipcount);
|
||||
|
||||
if (textureType == TEXTURE_CUBE && w != h)
|
||||
throw love::Exception("Cube images must have equal widths and heights for each cube face.");
|
||||
|
||||
int mipw = w;
|
||||
int miph = h;
|
||||
int mipslices = slicecount;
|
||||
|
||||
for (int mip = 0; mip < mipcount; mip++)
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
{
|
||||
slicecount = getSliceCount(mip);
|
||||
|
||||
if (slicecount != mipslices)
|
||||
throw love::Exception("Invalid number of image data layers in mipmap level %d (expected %d, got %d)", mip+1, mipslices, slicecount);
|
||||
}
|
||||
|
||||
for (int slice = 0; slice < slicecount; slice++)
|
||||
{
|
||||
auto slicedata = get(slice, mip);
|
||||
|
||||
if (slicedata == nullptr)
|
||||
throw love::Exception("Missing image data (slice %d, mipmap level %d)", slice+1, mip+1);
|
||||
|
||||
int realw = slicedata->getWidth();
|
||||
int realh = slicedata->getHeight();
|
||||
|
||||
if (getMipmapCount(slice) != mipcount)
|
||||
throw love::Exception("All Image layers must have the same mipmap count.");
|
||||
|
||||
if (mipw != realw)
|
||||
throw love::Exception("Width of image data (slice %d, mipmap level %d) is incorrect (expected %d, got %d)", slice+1, mip+1, mipw, realw);
|
||||
|
||||
if (miph != realh)
|
||||
throw love::Exception("Height of image data (slice %d, mipmap level %d) is incorrect (expected %d, got %d)", slice+1, mip+1, miph, realh);
|
||||
|
||||
if (format != slicedata->getFormat())
|
||||
throw love::Exception("All Image slices and mipmaps must have the same pixel format.");
|
||||
}
|
||||
|
||||
mipw = std::max(mipw / 2, 1);
|
||||
miph = std::max(miph / 2, 1);
|
||||
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
mipslices = std::max(mipslices / 2, 1);
|
||||
}
|
||||
|
||||
if (mipcount > 1)
|
||||
return MIPMAPS_DATA;
|
||||
else
|
||||
return MIPMAPS_NONE;
|
||||
}
|
||||
|
||||
bool Image::getConstant(const char *in, SettingType &out)
|
||||
{
|
||||
return settingTypes.find(in, out);
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include "common/config.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "common/math.h"
|
||||
#include "image/ImageData.h"
|
||||
#include "image/CompressedImageData.h"
|
||||
#include "Texture.h"
|
||||
|
||||
namespace love
|
||||
@@ -39,13 +37,6 @@ public:
|
||||
|
||||
static love::Type type;
|
||||
|
||||
enum MipmapsType
|
||||
{
|
||||
MIPMAPS_NONE,
|
||||
MIPMAPS_DATA,
|
||||
MIPMAPS_GENERATED,
|
||||
};
|
||||
|
||||
enum SettingType
|
||||
{
|
||||
SETTING_MIPMAPS,
|
||||
@@ -61,36 +52,6 @@ public:
|
||||
float dpiScale = 1.0f;
|
||||
};
|
||||
|
||||
struct Slices
|
||||
{
|
||||
public:
|
||||
|
||||
Slices(TextureType textype);
|
||||
|
||||
void clear();
|
||||
void set(int slice, int mipmap, love::image::ImageDataBase *data);
|
||||
love::image::ImageDataBase *get(int slice, int mipmap) const;
|
||||
|
||||
void add(love::image::CompressedImageData *cdata, int startslice, int startmip, bool addallslices, bool addallmips);
|
||||
|
||||
int getSliceCount(int mip = 0) const;
|
||||
int getMipmapCount(int slice = 0) const;
|
||||
|
||||
MipmapsType validate() const;
|
||||
|
||||
TextureType getTextureType() const { return textureType; }
|
||||
|
||||
private:
|
||||
|
||||
TextureType textureType;
|
||||
|
||||
// For 2D/Cube/2DArray texture types, each element in the data array has
|
||||
// an array of mipmap levels. For 3D texture types, each mipmap level
|
||||
// has an array of layers.
|
||||
std::vector<std::vector<StrongRef<love::image::ImageDataBase>>> data;
|
||||
|
||||
}; // Slices
|
||||
|
||||
virtual ~Image();
|
||||
|
||||
void replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, int x, int y, bool reloadmipmaps);
|
||||
|
||||
@@ -382,6 +382,165 @@ bool Texture::validateDimensions(bool throwException) const
|
||||
return success;
|
||||
}
|
||||
|
||||
Texture::Slices::Slices(TextureType textype)
|
||||
: textureType(textype)
|
||||
{
|
||||
}
|
||||
|
||||
void Texture::Slices::clear()
|
||||
{
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void Texture::Slices::set(int slice, int mipmap, love::image::ImageDataBase *d)
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
{
|
||||
if (mipmap >= (int) data.size())
|
||||
data.resize(mipmap + 1);
|
||||
|
||||
if (slice >= (int) data[mipmap].size())
|
||||
data[mipmap].resize(slice + 1);
|
||||
|
||||
data[mipmap][slice].set(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (slice >= (int) data.size())
|
||||
data.resize(slice + 1);
|
||||
|
||||
if (mipmap >= (int) data[slice].size())
|
||||
data[slice].resize(mipmap + 1);
|
||||
|
||||
data[slice][mipmap].set(d);
|
||||
}
|
||||
}
|
||||
|
||||
love::image::ImageDataBase *Texture::Slices::get(int slice, int mipmap) const
|
||||
{
|
||||
if (slice < 0 || slice >= getSliceCount(mipmap))
|
||||
return nullptr;
|
||||
|
||||
if (mipmap < 0 || mipmap >= getMipmapCount(slice))
|
||||
return nullptr;
|
||||
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
return data[mipmap][slice].get();
|
||||
else
|
||||
return data[slice][mipmap].get();
|
||||
}
|
||||
|
||||
void Texture::Slices::add(love::image::CompressedImageData *cdata, int startslice, int startmip, bool addallslices, bool addallmips)
|
||||
{
|
||||
int slicecount = addallslices ? cdata->getSliceCount() : 1;
|
||||
int mipcount = addallmips ? cdata->getMipmapCount() : 1;
|
||||
|
||||
for (int mip = 0; mip < mipcount; mip++)
|
||||
{
|
||||
for (int slice = 0; slice < slicecount; slice++)
|
||||
set(startslice + slice, startmip + mip, cdata->getSlice(slice, mip));
|
||||
}
|
||||
}
|
||||
|
||||
int Texture::Slices::getSliceCount(int mip) const
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
{
|
||||
if (mip < 0 || mip >= (int) data.size())
|
||||
return 0;
|
||||
|
||||
return (int) data[mip].size();
|
||||
}
|
||||
else
|
||||
return (int) data.size();
|
||||
}
|
||||
|
||||
int Texture::Slices::getMipmapCount(int slice) const
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
return (int) data.size();
|
||||
else
|
||||
{
|
||||
if (slice < 0 || slice >= (int) data.size())
|
||||
return 0;
|
||||
|
||||
return data[slice].size();
|
||||
}
|
||||
}
|
||||
|
||||
bool Texture::Slices::validate() const
|
||||
{
|
||||
int slicecount = getSliceCount();
|
||||
int mipcount = getMipmapCount(0);
|
||||
|
||||
if (slicecount == 0 || mipcount == 0)
|
||||
throw love::Exception("At least one ImageData or CompressedImageData is required!");
|
||||
|
||||
if (textureType == TEXTURE_CUBE && slicecount != 6)
|
||||
throw love::Exception("Cube textures must have exactly 6 sides.");
|
||||
|
||||
image::ImageDataBase *firstdata = get(0, 0);
|
||||
|
||||
int w = firstdata->getWidth();
|
||||
int h = firstdata->getHeight();
|
||||
int depth = textureType == TEXTURE_VOLUME ? slicecount : 1;
|
||||
PixelFormat format = firstdata->getFormat();
|
||||
|
||||
int expectedmips = Texture::getTotalMipmapCount(w, h, depth);
|
||||
|
||||
if (mipcount != expectedmips && mipcount != 1)
|
||||
throw love::Exception("Image does not have all required mipmap levels (expected %d, got %d)", expectedmips, mipcount);
|
||||
|
||||
if (textureType == TEXTURE_CUBE && w != h)
|
||||
throw love::Exception("Cube images must have equal widths and heights for each cube face.");
|
||||
|
||||
int mipw = w;
|
||||
int miph = h;
|
||||
int mipslices = slicecount;
|
||||
|
||||
for (int mip = 0; mip < mipcount; mip++)
|
||||
{
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
{
|
||||
slicecount = getSliceCount(mip);
|
||||
|
||||
if (slicecount != mipslices)
|
||||
throw love::Exception("Invalid number of image data layers in mipmap level %d (expected %d, got %d)", mip+1, mipslices, slicecount);
|
||||
}
|
||||
|
||||
for (int slice = 0; slice < slicecount; slice++)
|
||||
{
|
||||
auto slicedata = get(slice, mip);
|
||||
|
||||
if (slicedata == nullptr)
|
||||
throw love::Exception("Missing image data (slice %d, mipmap level %d)", slice+1, mip+1);
|
||||
|
||||
int realw = slicedata->getWidth();
|
||||
int realh = slicedata->getHeight();
|
||||
|
||||
if (getMipmapCount(slice) != mipcount)
|
||||
throw love::Exception("All Image layers must have the same mipmap count.");
|
||||
|
||||
if (mipw != realw)
|
||||
throw love::Exception("Width of image data (slice %d, mipmap level %d) is incorrect (expected %d, got %d)", slice+1, mip+1, mipw, realw);
|
||||
|
||||
if (miph != realh)
|
||||
throw love::Exception("Height of image data (slice %d, mipmap level %d) is incorrect (expected %d, got %d)", slice+1, mip+1, miph, realh);
|
||||
|
||||
if (format != slicedata->getFormat())
|
||||
throw love::Exception("All Image slices and mipmaps must have the same pixel format.");
|
||||
}
|
||||
|
||||
mipw = std::max(mipw / 2, 1);
|
||||
miph = std::max(miph / 2, 1);
|
||||
|
||||
if (textureType == TEXTURE_VOLUME)
|
||||
mipslices = std::max(mipslices / 2, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::getConstant(const char *in, TextureType &out)
|
||||
{
|
||||
return texTypes.find(in, out);
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "vertex.h"
|
||||
#include "renderstate.h"
|
||||
#include "Resource.h"
|
||||
#include "image/ImageData.h"
|
||||
#include "image/CompressedImageData.h"
|
||||
|
||||
// C
|
||||
#include <stddef.h>
|
||||
@@ -96,6 +98,43 @@ public:
|
||||
WrapMode r = WRAP_CLAMP;
|
||||
};
|
||||
|
||||
enum MipmapsType
|
||||
{
|
||||
MIPMAPS_NONE,
|
||||
MIPMAPS_DATA,
|
||||
MIPMAPS_GENERATED,
|
||||
};
|
||||
|
||||
struct Slices
|
||||
{
|
||||
public:
|
||||
|
||||
Slices(TextureType textype);
|
||||
|
||||
void clear();
|
||||
void set(int slice, int mipmap, love::image::ImageDataBase *data);
|
||||
love::image::ImageDataBase *get(int slice, int mipmap) const;
|
||||
|
||||
void add(love::image::CompressedImageData *cdata, int startslice, int startmip, bool addallslices, bool addallmips);
|
||||
|
||||
int getSliceCount(int mip = 0) const;
|
||||
int getMipmapCount(int slice = 0) const;
|
||||
|
||||
bool validate() const;
|
||||
|
||||
TextureType getTextureType() const { return textureType; }
|
||||
|
||||
private:
|
||||
|
||||
TextureType textureType;
|
||||
|
||||
// For 2D/Cube/2DArray texture types, each element in the data array has
|
||||
// an array of mipmap levels. For 3D texture types, each mipmap level
|
||||
// has an array of layers.
|
||||
std::vector<std::vector<StrongRef<love::image::ImageDataBase>>> data;
|
||||
|
||||
}; // Slices
|
||||
|
||||
static Filter defaultFilter;
|
||||
static FilterMode defaultMipmapFilter;
|
||||
static float defaultMipmapSharpness;
|
||||
|
||||
@@ -130,7 +130,7 @@ love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferType type, size_t
|
||||
return CreateStreamBuffer(type, size);
|
||||
}
|
||||
|
||||
love::graphics::Image *Graphics::newImage(const Image::Slices &data, const Image::Settings &settings)
|
||||
love::graphics::Image *Graphics::newImage(const Texture::Slices &data, const Image::Settings &settings)
|
||||
{
|
||||
return new Image(data, settings);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
// Implements Module.
|
||||
const char *getName() const override;
|
||||
|
||||
love::graphics::Image *newImage(const Image::Slices &data, const Image::Settings &settings) override;
|
||||
love::graphics::Image *newImage(const Texture::Slices &data, const Image::Settings &settings) override;
|
||||
love::graphics::Image *newImage(TextureType textype, PixelFormat format, int width, int height, int slices, const Image::Settings &settings) override;
|
||||
love::graphics::Canvas *newCanvas(const Canvas::Settings &settings) override;
|
||||
love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) override;
|
||||
|
||||
@@ -757,7 +757,7 @@ getImageData(lua_State *L, int idx, bool allowcompressed, float *dpiscale)
|
||||
return std::make_pair(idata, cdata);
|
||||
}
|
||||
|
||||
static int w__pushNewImage(lua_State *L, Image::Slices &slices, const Image::Settings &settings)
|
||||
static int w__pushNewImage(lua_State *L, Texture::Slices &slices, const Image::Settings &settings)
|
||||
{
|
||||
StrongRef<Image> i;
|
||||
luax_catchexcept(L,
|
||||
@@ -773,7 +773,7 @@ int w_newCubeImage(lua_State *L)
|
||||
{
|
||||
luax_checkgraphicscreated(L);
|
||||
|
||||
Image::Slices slices(TEXTURE_CUBE);
|
||||
Texture::Slices slices(TEXTURE_CUBE);
|
||||
|
||||
bool dpiscaleset = false;
|
||||
Image::Settings settings = w__optImageSettings(L, 2, dpiscaleset);
|
||||
@@ -867,7 +867,7 @@ int w_newArrayImage(lua_State *L)
|
||||
{
|
||||
luax_checkgraphicscreated(L);
|
||||
|
||||
Image::Slices slices(TEXTURE_2D_ARRAY);
|
||||
Texture::Slices slices(TEXTURE_2D_ARRAY);
|
||||
|
||||
bool dpiscaleset = false;
|
||||
Image::Settings settings = w__optImageSettings(L, 2, dpiscaleset);
|
||||
@@ -933,7 +933,7 @@ int w_newVolumeImage(lua_State *L)
|
||||
|
||||
auto imagemodule = Module::getInstance<love::image::Image>(Module::M_IMAGE);
|
||||
|
||||
Image::Slices slices(TEXTURE_VOLUME);
|
||||
Texture::Slices slices(TEXTURE_VOLUME);
|
||||
|
||||
bool dpiscaleset = false;
|
||||
Image::Settings settings = w__optImageSettings(L, 2, dpiscaleset);
|
||||
@@ -1004,7 +1004,7 @@ int w_newImage(lua_State *L)
|
||||
{
|
||||
luax_checkgraphicscreated(L);
|
||||
|
||||
Image::Slices slices(TEXTURE_2D);
|
||||
Texture::Slices slices(TEXTURE_2D);
|
||||
|
||||
bool dpiscaleset = false;
|
||||
Image::Settings settings = w__optImageSettings(L, 2, dpiscaleset);
|
||||
|
||||
Reference in New Issue
Block a user