mirror of
https://github.com/love2d/love.git
synced 2026-08-20 20:49:54 +02:00
Add support for partial Image updates via Image:replacePixels(imagedata [, sliceindex, mipmap, x, y]) with a smaller-sized ImageData.
Also updated the argument order of Canvas:newImageData to match: (sliceindex, mipmap, x, y, w, h).
This commit is contained in:
@@ -99,7 +99,7 @@ void Image::init(PixelFormat fmt, int w, int h, const Settings &settings)
|
|||||||
initQuad();
|
initQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::uploadImageData(love::image::ImageDataBase *d, int level, int slice, const Rect &rect)
|
void Image::uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y)
|
||||||
{
|
{
|
||||||
love::image::ImageData *id = dynamic_cast<love::image::ImageData *>(d);
|
love::image::ImageData *id = dynamic_cast<love::image::ImageData *>(d);
|
||||||
|
|
||||||
@@ -107,10 +107,11 @@ void Image::uploadImageData(love::image::ImageDataBase *d, int level, int slice,
|
|||||||
if (id != nullptr)
|
if (id != nullptr)
|
||||||
lock.setLock(id->getMutex());
|
lock.setLock(id->getMutex());
|
||||||
|
|
||||||
|
Rect rect = {x, y, d->getWidth(), d->getHeight()};
|
||||||
uploadByteData(d->getFormat(), d->getData(), d->getSize(), level, slice, rect);
|
uploadByteData(d->getFormat(), d->getData(), d->getSize(), level, slice, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, const Rect &rect, bool reloadmipmaps)
|
void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, int x, int y, bool reloadmipmaps)
|
||||||
{
|
{
|
||||||
// No effect if the texture hasn't been created yet.
|
// No effect if the texture hasn't been created yet.
|
||||||
if (getHandle() == 0 || usingDefaultTexture)
|
if (getHandle() == 0 || usingDefaultTexture)
|
||||||
@@ -129,6 +130,8 @@ void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap,
|
|||||||
throw love::Exception("Invalid image slice index %d.", slice + 1);
|
throw love::Exception("Invalid image slice index %d.", slice + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect rect = {x, y, d->getWidth(), d->getHeight()};
|
||||||
|
|
||||||
int mipw = getPixelWidth(mipmap);
|
int mipw = getPixelWidth(mipmap);
|
||||||
int miph = getPixelHeight(mipmap);
|
int miph = getPixelHeight(mipmap);
|
||||||
|
|
||||||
@@ -144,16 +147,18 @@ void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap,
|
|||||||
throw love::Exception("Image does not store ImageData!");
|
throw love::Exception("Image does not store ImageData!");
|
||||||
|
|
||||||
Rect currect = {0, 0, oldd->getWidth(), oldd->getHeight()};
|
Rect currect = {0, 0, oldd->getWidth(), oldd->getHeight()};
|
||||||
Rect newdrect = {0, 0, d->getWidth(), d->getHeight()};
|
|
||||||
|
|
||||||
// We can only replace the internal Data (used when reloading due to setMode)
|
// We can only replace the internal Data (used when reloading due to setMode)
|
||||||
// if the dimensions match.
|
// if the dimensions match. We also don't currently support partial updates
|
||||||
if (rect == currect && rect == newdrect)
|
// of compressed textures.
|
||||||
|
if (rect == currect)
|
||||||
data.set(slice, mipmap, d);
|
data.set(slice, mipmap, d);
|
||||||
|
else if (isPixelFormatCompressed(d->getFormat()))
|
||||||
|
throw love::Exception("Compressed textures only support replacing the entire Image.");
|
||||||
|
|
||||||
Graphics::flushStreamDrawsGlobal();
|
Graphics::flushStreamDrawsGlobal();
|
||||||
|
|
||||||
uploadImageData(d, mipmap, slice, rect);
|
uploadImageData(d, mipmap, slice, x, y);
|
||||||
|
|
||||||
if (reloadmipmaps && mipmap == 0 && getMipmapCount() > 1)
|
if (reloadmipmaps && mipmap == 0 && getMipmapCount() > 1)
|
||||||
generateMipmaps();
|
generateMipmaps();
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public:
|
|||||||
|
|
||||||
virtual ~Image();
|
virtual ~Image();
|
||||||
|
|
||||||
void replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, const Rect &rect, bool reloadmipmaps);
|
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);
|
void replacePixels(const void *data, size_t size, int slice, int mipmap, const Rect &rect, bool reloadmipmaps);
|
||||||
|
|
||||||
bool isFormatLinear() const;
|
bool isFormatLinear() const;
|
||||||
@@ -112,7 +112,7 @@ protected:
|
|||||||
Image(const Slices &data, const Settings &settings);
|
Image(const Slices &data, const Settings &settings);
|
||||||
Image(TextureType textype, PixelFormat format, int width, int height, int slices, const Settings &settings);
|
Image(TextureType textype, PixelFormat format, int width, int height, int slices, const Settings &settings);
|
||||||
|
|
||||||
void uploadImageData(love::image::ImageDataBase *d, int level, int slice, const Rect &rect);
|
void uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y);
|
||||||
virtual void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) = 0;
|
virtual void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) = 0;
|
||||||
|
|
||||||
virtual void generateMipmaps() = 0;
|
virtual void generateMipmaps() = 0;
|
||||||
|
|||||||
@@ -133,10 +133,7 @@ void Image::loadData()
|
|||||||
love::image::ImageDataBase *id = data.get(slice, mip);
|
love::image::ImageDataBase *id = data.get(slice, mip);
|
||||||
|
|
||||||
if (id != nullptr)
|
if (id != nullptr)
|
||||||
{
|
uploadImageData(id, mip, slice, 0, 0);
|
||||||
Rect r = {0, 0, id->getWidth(), id->getHeight()};
|
|
||||||
uploadImageData(id, mip, slice, r);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w = std::max(w / 2, 1);
|
w = std::max(w / 2, 1);
|
||||||
|
|||||||
@@ -94,15 +94,17 @@ int w_Canvas_newImageData(lua_State *L)
|
|||||||
int mipmap = 0;
|
int mipmap = 0;
|
||||||
Rect rect = {0, 0, canvas->getPixelWidth(), canvas->getPixelHeight()};
|
Rect rect = {0, 0, canvas->getPixelWidth(), canvas->getPixelHeight()};
|
||||||
|
|
||||||
if (!lua_isnoneornil(L, 2))
|
if (canvas->getTextureType() != TEXTURE_2D)
|
||||||
{
|
slice = (int) luaL_checkinteger(L, 2) - 1;
|
||||||
rect.x = (int) luaL_checkinteger(L, 2);
|
|
||||||
rect.y = (int) luaL_checkinteger(L, 3);
|
|
||||||
rect.w = (int) luaL_checkinteger(L, 4);
|
|
||||||
rect.h = (int) luaL_checkinteger(L, 5);
|
|
||||||
|
|
||||||
slice = (int) luaL_optinteger(L, 6, 1) - 1;
|
mipmap = (int) luaL_optinteger(L, 3, 1) - 1;
|
||||||
mipmap = (int) luaL_optinteger(L, 7, 1) - 1;
|
|
||||||
|
if (!lua_isnoneornil(L, 4))
|
||||||
|
{
|
||||||
|
rect.x = (int) luaL_checkinteger(L, 4);
|
||||||
|
rect.y = (int) luaL_checkinteger(L, 5);
|
||||||
|
rect.w = (int) luaL_checkinteger(L, 6);
|
||||||
|
rect.h = (int) luaL_checkinteger(L, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
love::image::ImageData *img = nullptr;
|
love::image::ImageData *img = nullptr;
|
||||||
|
|||||||
@@ -52,19 +52,25 @@ int w_Image_replacePixels(lua_State *L)
|
|||||||
|
|
||||||
int slice = 0;
|
int slice = 0;
|
||||||
int mipmap = 0;
|
int mipmap = 0;
|
||||||
Rect r = {0, 0, id->getWidth(), id->getHeight()};
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
bool reloadmipmaps = i->getMipmapsType() == Image::MIPMAPS_GENERATED;
|
bool reloadmipmaps = i->getMipmapsType() == Image::MIPMAPS_GENERATED;
|
||||||
|
|
||||||
if (i->getTextureType() != TEXTURE_2D)
|
if (i->getTextureType() != TEXTURE_2D)
|
||||||
{
|
|
||||||
slice = (int) luaL_checkinteger(L, 3) - 1;
|
slice = (int) luaL_checkinteger(L, 3) - 1;
|
||||||
if (!reloadmipmaps)
|
|
||||||
mipmap = (int) luaL_optinteger(L, 4, 1) - 1;
|
|
||||||
}
|
|
||||||
else if (!reloadmipmaps)
|
|
||||||
mipmap = (int) luaL_optinteger(L, 3, 1) - 1;
|
|
||||||
|
|
||||||
luax_catchexcept(L, [&](){ i->replacePixels(id, slice, mipmap, r, reloadmipmaps); });
|
mipmap = (int) luaL_optinteger(L, 4, 1) - 1;
|
||||||
|
|
||||||
|
if (!lua_isnoneornil(L, 5))
|
||||||
|
{
|
||||||
|
x = (int) luaL_checkinteger(L, 5);
|
||||||
|
y = (int) luaL_checkinteger(L, 6);
|
||||||
|
|
||||||
|
if (reloadmipmaps)
|
||||||
|
reloadmipmaps = luax_optboolean(L, 7, reloadmipmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
luax_catchexcept(L, [&](){ i->replacePixels(id, slice, mipmap, x, y, reloadmipmaps); });
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user