mirror of
https://github.com/opentx/opentx.git
synced 2025-07-17 21:35:27 +03:00
Prevent Lua from allocating all heap memory (Horus) (#4440)
* Fixes #4284: Prevent Lua from allocating all heap memory (Horus) Lua bitmap functions cleanup and docs update Added x or y < 0 check to drawBitmap() * Proper float constant
This commit is contained in:
parent
be61e07939
commit
e80c4c858e
8 changed files with 94 additions and 31 deletions
|
@ -325,10 +325,19 @@ static int luaLcdDrawSource(lua_State *L)
|
|||
/*luadoc
|
||||
@function Bitmap.open(name)
|
||||
|
||||
Loads a bitmap in memory, for later use with lcd.drawBitmap()
|
||||
Loads a bitmap in memory, for later use with lcd.drawBitmap(). Bitmaps should be loaded only
|
||||
once, returned object should be stored and used for drawing. If loading fails for whatever
|
||||
reason the resulting bitmap object will have width and height set to zero.
|
||||
|
||||
Bitmap loading can fail if:
|
||||
* File is not found or contains invalid image
|
||||
* System is low on memory
|
||||
* Combined memory usage of all Lua script bitmaps exceeds certain value
|
||||
|
||||
@param name (string) full path to the bitmap on SD card (i.e. “/IMAGES/test.bmp”)
|
||||
|
||||
@retval bitmap (object) a bitmap object that can be used with other bitmap functions
|
||||
|
||||
@notice Only available on Horus
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
|
@ -337,18 +346,25 @@ static int luaOpenBitmap(lua_State * L)
|
|||
{
|
||||
const char * filename = luaL_checkstring(L, 1);
|
||||
|
||||
BitmapBuffer ** ptr = (BitmapBuffer **)lua_newuserdata(L, sizeof(BitmapBuffer *));
|
||||
*ptr = BitmapBuffer::load(filename);
|
||||
BitmapBuffer ** b = (BitmapBuffer **)lua_newuserdata(L, sizeof(BitmapBuffer *));
|
||||
|
||||
if (*ptr == NULL && G(L)->gcrunning) {
|
||||
luaC_fullgc(L, 1); /* try to free some memory... */
|
||||
*ptr = BitmapBuffer::load(filename); /* try again */
|
||||
if (luaExtraMemoryUsage > LUA_MEM_EXTRA_MAX) {
|
||||
// already allocated more than max allowed, fail
|
||||
TRACE("luaOpenBitmap: Error, using too much memory %u/%u", luaExtraMemoryUsage, LUA_MEM_EXTRA_MAX);
|
||||
*b = 0;
|
||||
}
|
||||
else {
|
||||
*b = BitmapBuffer::load(filename);
|
||||
if (*b == NULL && G(L)->gcrunning) {
|
||||
luaC_fullgc(L, 1); /* try to free some memory... */
|
||||
*b = BitmapBuffer::load(filename); /* try again */
|
||||
}
|
||||
}
|
||||
|
||||
if (*ptr) {
|
||||
uint32_t size = (*ptr)->getDataSize();
|
||||
if (*b) {
|
||||
uint32_t size = (*b)->getDataSize();
|
||||
luaExtraMemoryUsage += size;
|
||||
TRACE("luaOpenBitmap: %p (%u)", *ptr, size);
|
||||
TRACE("luaOpenBitmap: %p (%u)", *b, size);
|
||||
}
|
||||
|
||||
luaL_getmetatable(L, LUA_BITMAPHANDLE);
|
||||
|
@ -364,13 +380,16 @@ static BitmapBuffer * checkBitmap(lua_State * L, int index)
|
|||
return *b;
|
||||
}
|
||||
|
||||
|
||||
/*luadoc
|
||||
@function Bitmap.getSize(name)
|
||||
|
||||
Return width, heigh of a bitmap in memory
|
||||
Return width, height of a bitmap object
|
||||
|
||||
@param bitmap (pointer) point to a bitmap previously opened with Bipmap.open()
|
||||
@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open()
|
||||
|
||||
@retval multiple returns 2 values:
|
||||
* (number) width in pixels
|
||||
* (number) height in pixels
|
||||
|
||||
@notice Only available on Horus
|
||||
|
||||
|
@ -378,7 +397,7 @@ Return width, heigh of a bitmap in memory
|
|||
*/
|
||||
static int luaGetBitmapSize(lua_State * L)
|
||||
{
|
||||
BitmapBuffer * b = checkBitmap(L, 1);
|
||||
const BitmapBuffer * b = checkBitmap(L, 1);
|
||||
if (b) {
|
||||
lua_pushinteger(L, b->getWidth());
|
||||
lua_pushinteger(L, b->getHeight());
|
||||
|
@ -392,11 +411,18 @@ static int luaGetBitmapSize(lua_State * L)
|
|||
|
||||
static int luaDestroyBitmap(lua_State * L)
|
||||
{
|
||||
BitmapBuffer * ptr = checkBitmap(L, 1);
|
||||
uint32_t size = ptr->getDataSize();
|
||||
TRACE("luaDestroyBitmap: %p (%u)", ptr, size);
|
||||
if (luaExtraMemoryUsage > size) luaExtraMemoryUsage -= size;
|
||||
delete ptr;
|
||||
BitmapBuffer * b = checkBitmap(L, 1);
|
||||
if (b) {
|
||||
uint32_t size = b->getDataSize();
|
||||
TRACE("luaDestroyBitmap: %p (%u)", b, size);
|
||||
if (luaExtraMemoryUsage >= size) {
|
||||
luaExtraMemoryUsage -= size;
|
||||
}
|
||||
else {
|
||||
luaExtraMemoryUsage = 0;
|
||||
}
|
||||
delete b;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -421,11 +447,12 @@ void registerBitmapClass(lua_State * L)
|
|||
|
||||
Displays a bitmap at (x,y)
|
||||
|
||||
@param bitmap (pointer) point to a bitmap previously opened with Bipmap.open()
|
||||
@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open()
|
||||
|
||||
@param x,y (positive numbers) starting coordinates
|
||||
|
||||
@param scale (positive numbers) scale in %, 50 divides size by two, 100 is unchanged, 200 doubles size
|
||||
@param scale (positive numbers) scale in %, 50 divides size by two, 100 is unchanged, 200 doubles size.
|
||||
Omitting scale draws image in 1:1 scale and is faster than specifying 100 for scale.
|
||||
|
||||
@notice Only available on Horus
|
||||
|
||||
|
@ -434,15 +461,19 @@ Displays a bitmap at (x,y)
|
|||
static int luaLcdDrawBitmap(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed) return 0;
|
||||
const BitmapBuffer * bitmap = checkBitmap(L, 1);
|
||||
int x = luaL_checkinteger(L, 2);
|
||||
int y = luaL_checkinteger(L, 3);
|
||||
unsigned scale = luaL_optunsigned(L, 4, 0);
|
||||
const BitmapBuffer * b = checkBitmap(L, 1);
|
||||
|
||||
if (bitmap) {
|
||||
lcd->drawBitmap(x, y, bitmap, 0, 0, 0, 0, (float) scale/100);
|
||||
if (b) {
|
||||
unsigned int x = luaL_checkunsigned(L, 2);
|
||||
unsigned int y = luaL_checkunsigned(L, 3);
|
||||
unsigned int scale = luaL_optunsigned(L, 4, 0);
|
||||
if (scale) {
|
||||
lcd->drawBitmap(x, y, b, 0, 0, 0, 0, scale/100.0f);
|
||||
}
|
||||
else {
|
||||
lcd->drawBitmap(x, y, b);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#elif LCD_DEPTH > 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue