From e82d1dfe5455291560f51e8ee59851e4e9790f46 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 21 Jan 2015 16:52:56 -0400 Subject: [PATCH 1/4] =?UTF-8?q?Added=20Lua=205.3's=20UTF-8=20module=20to?= =?UTF-8?q?=20L=C3=96VE.=20Resolves=20issue=20#951.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The module must be required before use, i.e. utf8 = require("utf8"). API documentation can be found here: http://www.lua.org/manual/5.3/manual.html#6.5 Removing the last unicode character in a string (for proper backspace support in text boxes, for example) can be done using utf8.offset, e.g. text = text:sub(1, utf8.offset(text, -1) - 1). --- CMakeLists.txt | 13 + .../love-framework.xcodeproj/project.pbxproj | 20 ++ src/common/config.h | 1 + src/libraries/luautf8/lprefix.h | 45 +++ src/libraries/luautf8/lutf8lib.c | 290 ++++++++++++++++++ src/libraries/luautf8/lutf8lib.h | 17 + src/modules/love/love.cpp | 8 +- 7 files changed, 392 insertions(+), 2 deletions(-) create mode 100644 src/libraries/luautf8/lprefix.h create mode 100644 src/libraries/luautf8/lutf8lib.c create mode 100644 src/libraries/luautf8/lutf8lib.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5098f3b3e..9687928a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1001,6 +1001,18 @@ set(LOVE_SRC_3P_LUASOCKET add_library(love_3p_luasocket ${LOVE_SRC_3P_LUASOCKET}) target_link_libraries(love_3p_luasocket ${MEGA_LUA}) +# +# Lua 5.3's UTF-8 library +# +set(LOVE_SRC_3P_LUAUTF8 + src/libraries/luautf8/lprefix.h + src/libraries/luautf8/lutf8lib.c + src/libraries/luautf8/lutf8lib.h +) + +add_library(love_3p_luautf8 ${LOVE_SRC_3P_LUAUTF8}) +target_link_libraries(love_3p_luautf8 ${MEGA_LUA}) + # # noise1234 # @@ -1054,6 +1066,7 @@ set(LOVE_3P love_3p_ddsparse love_3p_enet love_3p_luasocket + love_3p_luautf8 love_3p_noise1234 love_3p_wuff ) diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj index e5caa0411..1b9622062 100644 --- a/platform/macosx/love-framework.xcodeproj/project.pbxproj +++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj @@ -272,6 +272,9 @@ FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; }; FA9FC0B0173D6E3E005027FF /* wrap_Window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9FC0AE173D6E3E005027FF /* wrap_Window.cpp */; }; FA9FC0B1173D6E3E005027FF /* wrap_Window.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9FC0AF173D6E3E005027FF /* wrap_Window.h */; }; + FAA0A45E1A704016009487CB /* lprefix.h in Headers */ = {isa = PBXBuildFile; fileRef = FAA0A45C1A704016009487CB /* lprefix.h */; }; + FAA0A45F1A704016009487CB /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA0A45D1A704016009487CB /* lutf8lib.c */; }; + FAA0A4611A70431A009487CB /* lutf8lib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAA0A4601A70431A009487CB /* lutf8lib.h */; }; FAA627CE18E7E1560080752D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAA627CD18E7E1560080752D /* CoreServices.framework */; }; FAAC6B02170A373B008A61C5 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAAC6B00170A373A008A61C5 /* CompressedData.cpp */; }; FAAC6B03170A373B008A61C5 /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAC6B01170A373A008A61C5 /* CompressedData.h */; }; @@ -832,6 +835,9 @@ FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = ""; }; FA9FC0AE173D6E3E005027FF /* wrap_Window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Window.cpp; sourceTree = ""; }; FA9FC0AF173D6E3E005027FF /* wrap_Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Window.h; sourceTree = ""; }; + FAA0A45C1A704016009487CB /* lprefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lprefix.h; sourceTree = ""; }; + FAA0A45D1A704016009487CB /* lutf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lutf8lib.c; sourceTree = ""; }; + FAA0A4601A70431A009487CB /* lutf8lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lutf8lib.h; sourceTree = ""; }; FAA627CD18E7E1560080752D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; FAAC6B00170A373A008A61C5 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = ""; }; FAAC6B01170A373A008A61C5 /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = ""; }; @@ -1392,6 +1398,7 @@ FAE010D7170DDE99006F29D0 /* ddsparse */, FA5FDC5E1788D548002F0ED2 /* enet */, 3AED1DE005A53DDB07902760 /* luasocket */, + FAA0A45B1A704016009487CB /* luautf8 */, FA0354691731F3A700284828 /* noise1234 */, 36C14C81334735EC54E33637 /* utf8 */, FAF6704318184FF800DBDEEA /* Wuff */, @@ -1920,6 +1927,16 @@ path = math; sourceTree = ""; }; + FAA0A45B1A704016009487CB /* luautf8 */ = { + isa = PBXGroup; + children = ( + FAA0A45C1A704016009487CB /* lprefix.h */, + FAA0A45D1A704016009487CB /* lutf8lib.c */, + FAA0A4601A70431A009487CB /* lutf8lib.h */, + ); + path = luautf8; + sourceTree = ""; + }; FAE010D7170DDE99006F29D0 /* ddsparse */ = { isa = PBXGroup; children = ( @@ -1976,6 +1993,7 @@ FAF272B616E3D46400CC193A /* Thread.h in Headers */, FAF272B816E3D46400CC193A /* threads.h in Headers */, FA5454C316F1310000D30303 /* MathModule.h in Headers */, + FAA0A45E1A704016009487CB /* lprefix.h in Headers */, FAAC6B03170A373B008A61C5 /* CompressedData.h in Headers */, FAE010DB170DDE99006F29D0 /* ddsinfo.h in Headers */, FAE010DD170DDE99006F29D0 /* ddsparse.h in Headers */, @@ -2011,6 +2029,7 @@ FA5FDC831788D548002F0ED2 /* types.h in Headers */, FA0A4BF5182E1AD600E1E4D2 /* MotorJoint.h in Headers */, FA5FDC841788D548002F0ED2 /* unix.h in Headers */, + FAA0A4611A70431A009487CB /* lutf8lib.h in Headers */, FA0A4BF1182E0C2800E1E4D2 /* b2MotorJoint.h in Headers */, FA5FDC851788D548002F0ED2 /* utility.h in Headers */, FAF6704D18184FF800DBDEEA /* wuff.h in Headers */, @@ -2320,6 +2339,7 @@ FA9FC0B0173D6E3E005027FF /* wrap_Window.cpp in Sources */, FAB0078F1740C12D00A9664D /* Joystick.cpp in Sources */, FAB007931740C28900A9664D /* Joystick.cpp in Sources */, + FAA0A45F1A704016009487CB /* lutf8lib.c in Sources */, FAB007971740C87D00A9664D /* wrap_Joystick.cpp in Sources */, FAC5710017402D1100D147E4 /* BezierCurve.cpp in Sources */, FAC5710217402D1100D147E4 /* wrap_BezierCurve.cpp in Sources */, diff --git a/src/common/config.h b/src/common/config.h index b0133c96f..dbf75e82f 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -109,6 +109,7 @@ # define LOVE_ENABLE_KEYBOARD_SDL # define LOVE_ENABLE_LOVE # define LOVE_ENABLE_LUASOCKET +# define LOVE_ENABLE_LUAUTF8 # define LOVE_ENABLE_MATH # define LOVE_ENABLE_MOUSE # define LOVE_ENABLE_MOUSE_SDL diff --git a/src/libraries/luautf8/lprefix.h b/src/libraries/luautf8/lprefix.h new file mode 100644 index 000000000..de52de7b9 --- /dev/null +++ b/src/libraries/luautf8/lprefix.h @@ -0,0 +1,45 @@ +/* +** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $ +** Definitions for Lua code that must come before any other header file +** See Copyright Notice in lutf8lib.c +*/ + +#ifndef lprefix_h +#define lprefix_h + + +/* +** Allows POSIX/XSI stuff +*/ +#if !defined(LUA_USE_C89) /* { */ + +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#elif _XOPEN_SOURCE == 0 +#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ +#endif + +/* +** Allows manipulation of large files in gcc and some other compilers +*/ +#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#endif + +#endif /* } */ + + +/* +** Windows stuff +*/ +#if defined(_WIN32) /* { */ + +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ +#endif + +#endif /* } */ + +#endif + diff --git a/src/libraries/luautf8/lutf8lib.c b/src/libraries/luautf8/lutf8lib.c new file mode 100644 index 000000000..6418e3113 --- /dev/null +++ b/src/libraries/luautf8/lutf8lib.c @@ -0,0 +1,290 @@ +/* +** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $ +** Standard library for UTF-8 manipulation +** Modified by the LOVE Development Team to work with Lua 5.1's API +*/ + +/****************************************************************************** + * Copyright (C) 1994-2015 Lua.org, PUC-Rio, 2015 LOVE Development Team. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ******************************************************************************/ + +#define lutf8lib_c + +#include "lprefix.h" + + +#include +#include +#include + +#include "lutf8lib.h" + +#include "lauxlib.h" +#include "lualib.h" + +#define MAXUNICODE 0x10FFFF + +#define iscont(p) ((*(p) & 0xC0) == 0x80) + + +/* from strlib */ +/* translate a relative string position: negative means back from end */ +static lua_Integer u_posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; +} + + +/* +** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. +*/ +static const char *utf8_decode (const char *o, int *val) { + static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + const unsigned char *s = (const unsigned char *)o; + unsigned int c = s[0]; + unsigned int res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else { + int count = 0; /* to count number of continuation bytes */ + while (c & 0x40) { /* still have continuation bytes? */ + int cc = s[++count]; /* read next byte */ + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ + c <<= 1; /* to test next bit */ + } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 3 || res > MAXUNICODE || res <= limits[count]) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (val) *val = res; + return (const char *)s + 1; /* +1 to include first byte */ +} + + +/* +** utf8len(s [, i [, j]]) --> number of characters that start in the +** range [i,j], or nil + current position if 's' is not well formed in +** that interval +*/ +static int utflen (lua_State *L) { + int n = 0; + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, + "initial position out of string"); + luaL_argcheck(L, --posj < (lua_Integer)len, 3, + "final position out of string"); + while (posi <= posj) { + const char *s1 = utf8_decode(s + posi, NULL); + if (s1 == NULL) { /* conversion error? */ + lua_pushnil(L); /* return nil ... */ + lua_pushinteger(L, posi + 1); /* ... and current position */ + return 2; + } + posi = s1 - s; + n++; + } + lua_pushinteger(L, n); + return 1; +} + + +/* +** codepoint(s, [i, [j]]) -> returns codepoints for all characters +** that start in the range [i,j] +*/ +static int codepoint (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); + int n; + const char *se; + luaL_argcheck(L, posi >= 1, 2, "out of range"); + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* (lua_Integer -> int) overflow? */ + return luaL_error(L, "string slice too long"); + luaL_checkstack(L, n, "string slice too long"); + n = 0; + se = s + pose; + for (s += posi - 1; s < se;) { + int code; + s = utf8_decode(s, &code); + if (s == NULL) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, code); + n++; + } + return n; +} + + +static void pushutfchar (lua_State *L, int arg) { + lua_Integer code = luaL_checkinteger(L, arg); + luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); + lua_pushfstring(L, "%U", (long)code); +} + + +/* +** utfchar(n1, n2, ...) -> char(n1)..char(n2)... +*/ +static int utfchar (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + if (n == 1) /* optimize common case of single char */ + pushutfchar(L, 1); + else { + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i = 1; i <= n; i++) { + pushutfchar(L, i); + luaL_addvalue(&b); + } + luaL_pushresult(&b); + } + return 1; +} + + +/* +** offset(s, n, [i]) -> index where n-th character counting from +** position 'i' starts; 0 means character at 'i'. +*/ +static int byteoffset (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = luaL_checkinteger(L, 2); + lua_Integer posi = (n >= 0) ? 1 : len + 1; + posi = u_posrelat(luaL_optinteger(L, 3, posi), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, + "position out of range"); + if (n == 0) { + /* find beginning of current byte sequence */ + while (posi > 0 && iscont(s + posi)) posi--; + } + else { + if (iscont(s + posi)) + luaL_error(L, "initial position is a continuation byte"); + if (n < 0) { + while (n < 0 && posi > 0) { /* move back */ + do { /* find beginning of previous character */ + posi--; + } while (posi > 0 && iscont(s + posi)); + n++; + } + } + else { + n--; /* do not move for 1st character */ + while (n > 0 && posi < (lua_Integer)len) { + do { /* find beginning of next character */ + posi++; + } while (iscont(s + posi)); /* (cannot pass final '\0') */ + n--; + } + } + } + if (n == 0) /* did it find given character? */ + lua_pushinteger(L, posi + 1); + else /* no such character */ + lua_pushnil(L); + return 1; +} + + +static int iter_aux (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = lua_tointeger(L, 2) - 1; + if (n < 0) /* first iteration? */ + n = 0; /* start from here */ + else if (n < (lua_Integer)len) { + n++; /* skip current byte */ + while (iscont(s + n)) n++; /* and its continuations */ + } + if (n >= (lua_Integer)len) + return 0; /* no more codepoints */ + else { + int code; + const char *next = utf8_decode(s + n, &code); + if (next == NULL || iscont(next)) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, n + 1); + lua_pushinteger(L, code); + return 2; + } +} + + +static int iter_codes (lua_State *L) { + luaL_checkstring(L, 1); + lua_pushcfunction(L, iter_aux); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; +} + + +/* pattern to match a single UTF-8 character */ +#if LUA_VERSION_NUM >= 502 +#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" +#else +/* lua 5.1 doesn't support literal null bytes in patterns */ +#define UTF8PATT "[%z\x01-\x7F\xC2-\xF4][\x80-\xBF]*" +#endif + + +static struct luaL_Reg funcs[] = { + {"offset", byteoffset}, + {"codepoint", codepoint}, + {"char", utfchar}, + {"len", utflen}, + {"codes", iter_codes}, + /* placeholders */ + {"charpattern", NULL}, + {NULL, NULL} +}; + + +/* modified version of luaopen_utf8, designed to work with lua 5.1-5.3 */ +int luaopen_luautf8 (lua_State *L) { + luaL_Reg *l; + lua_createtable(L, 0, (int) (sizeof(funcs) / sizeof(luaL_Reg)) - 1); + for (l = funcs; l->name != NULL; l++) { + if (l->func != NULL) { + lua_pushcfunction(L, l->func); + lua_setfield(L, -2, l->name); + } + } + lua_pushliteral(L, UTF8PATT); + lua_setfield(L, -2, "charpattern"); + return 1; +} + diff --git a/src/libraries/luautf8/lutf8lib.h b/src/libraries/luautf8/lutf8lib.h new file mode 100644 index 000000000..bb4627b57 --- /dev/null +++ b/src/libraries/luautf8/lutf8lib.h @@ -0,0 +1,17 @@ + +#ifndef LUAUTF8_LUTF8LIB_H +#define LUAUTF8_LUTF8LIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lua.h" + +LUALIB_API int luaopen_luautf8(lua_State *L); + +#ifdef __cplusplus +} +#endif + +#endif /* LOVE_LUAUTF8_LUTF8LIB_H */ diff --git a/src/modules/love/love.cpp b/src/modules/love/love.cpp index d30adc60e..fae80d244 100644 --- a/src/modules/love/love.cpp +++ b/src/modules/love/love.cpp @@ -43,6 +43,9 @@ #ifdef LOVE_ENABLE_ENET # include "libraries/enet/lua-enet.h" #endif +#ifdef LOVE_ENABLE_LUAUTF8 +# include "libraries/luautf8/lutf8lib.h" +#endif // Scripts #include "scripts/boot.lua.h" @@ -228,9 +231,7 @@ int luaopen_love(lua_State * L) // Preload module loaders. for (int i = 0; modules[i].name != 0; i++) - { love::luax_preload(L, modules[i].func, modules[i].name); - } #ifdef LOVE_ENABLE_LUASOCKET love::luasocket::__open(L); @@ -238,6 +239,9 @@ int luaopen_love(lua_State * L) #ifdef LOVE_ENABLE_ENET love::luax_preload(L, luaopen_enet, "enet"); #endif +#ifdef LOVE_ENABLE_LUAUTF8 + love::luax_preload(L, luaopen_luautf8, "utf8"); +#endif return 1; } From 18569979e96f58af5f3229d9a8288a99fa9ffe3a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 21 Jan 2015 18:23:16 -0400 Subject: [PATCH 2/4] Better cleanup when the graphics and window subsystems are destroyed and restarted. --- src/modules/graphics/opengl/Graphics.cpp | 2 ++ src/modules/window/sdl/Window.cpp | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 45cd09f52..bc8524da3 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -50,6 +50,8 @@ Graphics::Graphics() , created(false) , activeStencil(false) { + gl = OpenGL(); + states.reserve(10); states.push_back(DisplayState()); diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index 451d29e16..dac94e5cf 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -48,12 +48,18 @@ Window::Window() Window::~Window() { + if (context) + { + graphics::Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); + if (gfx != nullptr) + gfx->unSetMode(); + + SDL_GL_DeleteContext(context); + } + if (window) SDL_DestroyWindow(window); - if (context) - SDL_GL_DeleteContext(context); - SDL_QuitSubSystem(SDL_INIT_VIDEO); } From 5c46149afb9da82d5fee3489d99e913a94c7c08e Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 21 Jan 2015 21:46:33 -0400 Subject: [PATCH 3/4] Properly set shader dirty flags for love_ScreenSize when love.window.setMode is called. --- src/modules/graphics/opengl/Shader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index 5250a9f75..60129aaa9 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -218,6 +218,10 @@ void Shader::mapActiveUniforms() bool Shader::loadVolatile() { + // Recreating the shader program will invalidate uniforms that rely on these. + lastCanvas = (Canvas *) -1; + lastViewport = OpenGL::Viewport(); + // zero out active texture list activeTexUnits.clear(); activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0); @@ -304,6 +308,7 @@ bool Shader::loadVolatile() // make sure glUseProgram gets called. current = nullptr; attach(); + checkSetScreenParams(); } return true; From e71c15e65074a23eb1caba410ebc7acf29eca7dc Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 22 Jan 2015 02:16:49 -0400 Subject: [PATCH 4/4] Fixed a minor memory leak caused by certain rare error conditions in love.graphics.newCanvas. --- src/modules/graphics/opengl/Canvas.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index dc357762d..c08f0c3e1 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -560,7 +560,9 @@ bool Canvas::loadVolatile() if (glGetError() != GL_NO_ERROR) { - status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + gl.deleteTexture(texture); + texture = 0; + status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; return false; } @@ -584,7 +586,14 @@ bool Canvas::loadVolatile() status = strategy->createFBO(fbo, texture); if (status != GL_FRAMEBUFFER_COMPLETE) + { + if (fbo != 0) + { + strategy->deleteFBO(fbo, 0, 0); + fbo = 0; + } return false; + } clear(Color(0, 0, 0, 0));