diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp index 2866b0121..a4ac24f70 100644 --- a/src/modules/graphics/Canvas.cpp +++ b/src/modules/graphics/Canvas.cpp @@ -107,40 +107,6 @@ Texture::MipmapsMode Canvas::getMipmapsMode() const return settings.mipmaps; } -love::image::ImageData *Canvas::newImageData(love::image::Image *module, int slice, int mipmap, const Rect &r) -{ - if (!isReadable()) - throw love::Exception("Canvas:newImageData cannot be called on non-readable Canvases."); - - if (isPixelFormatDepthStencil(getPixelFormat())) - throw love::Exception("Canvas:newImageData cannot be called on Canvases with depth/stencil pixel formats."); - - if (r.x < 0 || r.y < 0 || r.w <= 0 || r.h <= 0 || (r.x + r.w) > getPixelWidth(mipmap) || (r.y + r.h) > getPixelHeight(mipmap)) - throw love::Exception("Invalid rectangle dimensions."); - - if (slice < 0 || (texType == TEXTURE_VOLUME && slice >= getDepth(mipmap)) - || (texType == TEXTURE_2D_ARRAY && slice >= layers) - || (texType == TEXTURE_CUBE && slice >= 6)) - { - throw love::Exception("Invalid slice index."); - } - - Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); - if (gfx != nullptr && gfx->isRenderTargetActive(this)) - throw love::Exception("Canvas:newImageData cannot be called while that Canvas is currently active."); - - PixelFormat dataformat = getLinearPixelFormat(getPixelFormat()); - - if (!image::ImageData::validPixelFormat(dataformat)) - { - const char *formatname = "unknown"; - love::getConstant(dataformat, formatname); - throw love::Exception("ImageData with the '%s' pixel format is not supported.", formatname); - } - - return module->newImageData(r.w, r.h, dataformat); -} - bool Canvas::getConstant(const char *in, SettingType &out) { return settingTypes.find(in, out); diff --git a/src/modules/graphics/Canvas.h b/src/modules/graphics/Canvas.h index d683e9d5d..9b18ef7e2 100644 --- a/src/modules/graphics/Canvas.h +++ b/src/modules/graphics/Canvas.h @@ -71,8 +71,6 @@ public: 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, SettingType &out); static bool getConstant(SettingType in, const char *&out); static const char *getConstant(SettingType in); diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 7d3185489..4aaa6a972 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -440,6 +440,43 @@ void Texture::replacePixels(const void *data, size_t size, int slice, int mipmap generateMipmaps(); } +love::image::ImageData *Texture::newImageData(love::image::Image *module, int slice, int mipmap, const Rect &r) +{ + if (!isReadable()) + throw love::Exception("Texture:newImageData cannot be called on non-readable Textures."); + + if (!isRenderTarget()) + throw love::Exception("Texture:newImageData can only be called on render target Textures."); + + if (isPixelFormatDepthStencil(getPixelFormat())) + throw love::Exception("Texture:newImageData cannot be called on Textures with depth/stencil pixel formats."); + + if (r.x < 0 || r.y < 0 || r.w <= 0 || r.h <= 0 || (r.x + r.w) > getPixelWidth(mipmap) || (r.y + r.h) > getPixelHeight(mipmap)) + throw love::Exception("Invalid rectangle dimensions."); + + if (slice < 0 || (texType == TEXTURE_VOLUME && slice >= getDepth(mipmap)) + || (texType == TEXTURE_2D_ARRAY && slice >= layers) + || (texType == TEXTURE_CUBE && slice >= 6)) + { + throw love::Exception("Invalid slice index."); + } + + Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); + if (gfx != nullptr && gfx->isRenderTargetActive(this)) + throw love::Exception("Texture:newImageData cannot be called while that Texture is an active render target."); + + PixelFormat dataformat = getLinearPixelFormat(getPixelFormat()); + + if (!image::ImageData::validPixelFormat(dataformat)) + { + const char *formatname = "unknown"; + love::getConstant(dataformat, formatname); + throw love::Exception("ImageData with the '%s' pixel format is not supported.", formatname); + } + + return module->newImageData(r.w, r.h, dataformat); +} + int Texture::getWidth(int mip) const { return std::max(width >> mip, 1); diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index c6823e707..eb4716c66 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -34,6 +34,7 @@ #include "renderstate.h" #include "Resource.h" #include "image/ImageData.h" +#include "image/Image.h" #include "image/CompressedImageData.h" // C @@ -187,6 +188,8 @@ public: virtual void generateMipmaps() = 0; + virtual love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect); + virtual ptrdiff_t getRenderTargetHandle() const = 0; TextureType getTextureType() const; diff --git a/src/modules/graphics/wrap_Canvas.cpp b/src/modules/graphics/wrap_Canvas.cpp index d62f582f3..40e493c1e 100644 --- a/src/modules/graphics/wrap_Canvas.cpp +++ b/src/modules/graphics/wrap_Canvas.cpp @@ -78,36 +78,6 @@ int w_Canvas_renderTo(lua_State *L) return 0; } -int w_Canvas_newImageData(lua_State *L) -{ - Canvas *canvas = luax_checkcanvas(L, 1); - love::image::Image *image = luax_getmodule(L, love::image::Image::type); - - int slice = 0; - int mipmap = 0; - Rect rect = {0, 0, canvas->getPixelWidth(), canvas->getPixelHeight()}; - - if (canvas->getTextureType() != TEXTURE_2D) - slice = (int) luaL_checkinteger(L, 2) - 1; - - mipmap = (int) luaL_optinteger(L, 3, 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; - luax_catchexcept(L, [&](){ img = canvas->newImageData(image, slice, mipmap, rect); }); - - luax_pushtype(L, img); - img->release(); - return 1; -} - int w_Canvas_getMipmapMode(lua_State *L) { Canvas *c = luax_checkcanvas(L, 1); @@ -122,7 +92,6 @@ int w_Canvas_getMipmapMode(lua_State *L) static const luaL_Reg w_Canvas_functions[] = { { "renderTo", w_Canvas_renderTo }, - { "newImageData", w_Canvas_newImageData }, { "getMipmapMode", w_Canvas_getMipmapMode }, { 0, 0 } }; diff --git a/src/modules/graphics/wrap_Texture.cpp b/src/modules/graphics/wrap_Texture.cpp index f4bcb653a..87143887c 100644 --- a/src/modules/graphics/wrap_Texture.cpp +++ b/src/modules/graphics/wrap_Texture.cpp @@ -358,6 +358,36 @@ int w_Texture_replacePixels(lua_State *L) return 0; } +int w_Texture_newImageData(lua_State *L) +{ + Texture *t = luax_checktexture(L, 1); + love::image::Image *image = luax_getmodule(L, love::image::Image::type); + + int slice = 0; + int mipmap = 0; + Rect rect = {0, 0, t->getPixelWidth(), t->getPixelHeight()}; + + if (t->getTextureType() != TEXTURE_2D) + slice = (int) luaL_checkinteger(L, 2) - 1; + + mipmap = (int) luaL_optinteger(L, 3, 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; + luax_catchexcept(L, [&](){ img = t->newImageData(image, slice, mipmap, rect); }); + + luax_pushtype(L, img); + img->release(); + return 1; +} + const luaL_Reg w_Texture_functions[] = { { "getTextureType", w_Texture_getTextureType }, @@ -386,6 +416,7 @@ const luaL_Reg w_Texture_functions[] = { "setDepthSampleMode", w_Texture_setDepthSampleMode }, { "generateMipmaps", w_Texture_generateMipmaps }, { "replacePixels", w_Texture_replacePixels }, + { "newImageData", w_Texture_newImageData }, { 0, 0 } };