diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8af83674..f5b00344e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -341,6 +341,7 @@ set(LOVE_SRC_MODULE_IMAGE_MAGPIE
src/modules/image/magpie/ddsHandler.h
src/modules/image/magpie/DevilHandler.cpp
src/modules/image/magpie/DevilHandler.h
+ src/modules/image/magpie/FormatHandler.cpp
src/modules/image/magpie/FormatHandler.h
src/modules/image/magpie/Image.cpp
src/modules/image/magpie/Image.h
diff --git a/changes.txt b/changes.txt
index 569cb7ef4..1401af364 100644
--- a/changes.txt
+++ b/changes.txt
@@ -5,11 +5,27 @@ LOVE 0.9.1 [Baby Inspector]
* Added Source:clone.
* Added ParticleSystem:clone.
- * Added Mesh:setWireframe and Mesh:isWireframe for debugging.
+ * Added ParticleSystem:moveTo, has smoother emitter movement compared to setPosition.
+ * Added ParticleSystem:setRelativeRotation.
+ * Added love.graphics.setWireframe for debugging.
+ * Added Mesh:setDrawRange and Mesh:getDrawRange.
+ * Added instancing support to Meshes with Mesh:setInstanceCount.
* Added CircleShape:getPoint and CircleShape:setPoint.
* Added Mesh/SpriteBatch/ParticleSystem:setTexture, accepts Canvases and Images.
+ * Added high-dpi window support for Retina displays in OS X, via the 'highdpi' window flag.
+ * Added love.window.getPixelScale.
+ * Added love.graphics.getSystemLimit.
+ * Added antialiasing support to Canvases.
+ * Added Canvas:getFSAA.
+ * Added 'love_ScreenSize' built-in variable in shaders.
+ * Added love.getVersion.
+ * Added support for gamma-correct rendering.
+ * Added love.graphics.isSupported("srgb").
+ * Added love.math.gammaToLinear and love.math.linearToGamma.
+ * Added RandomGenerator:getState and RandomGenerator:setState.
* Deprecated Mesh/SpriteBatch/ParticleSystem:setImage.
+ * Deprecated love.graphics.getMaxImageSize and love.graphics.getMaxPointSize.
* Fixed love.graphics.scale with negative values causing incorrect line widths.
* Fixed Joystick:isDown using 0-based button index arguments.
@@ -17,11 +33,20 @@ LOVE 0.9.1 [Baby Inspector]
* Fixed love.graphics.setCanvas() to restore the proper viewport and scissor rectangles.
* Fixed TrueType font glyphs which request a monochrome bitmap pixel mode.
* Fixed love.graphics.reset causing crashes when called in between love.graphics.push/pop.
+ * Fixed tab characters ("\t") to display properly with love.graphics.print.
+ * Fixed World:getBodyList and World:getJointList causing hard crashes.
+
+ * Renamed love.graphics.getMaxImageSize to love.graphics.getMaxTextureSize (old function still exists.)
* Updated the error text for love.filesystem’s module searchers when require fails.
* Updated the love.filesystem module searchers to be tried after package.preload instead of before.
* Updated love.graphics.newParticleSystem, newSpriteBatch, and newMesh to accept Canvases.
* Updated Canvas drawing code, texture coordinates are no longer flipped vertically.
+ * Updated Canvas:renderTo to work properly if a Canvas is currently active.
+ * Updated ParticleSystem:setEmissionRate to accept non-integer numbers.
+ * Updated Source:play to return a boolean indicating success.
+ * Updated t.console in conf.lua to create the console before modules are loaded in Windows.
+ * Updated Mesh vertex maps (index buffers) to use less space in VRAM.
LOVE 0.9.0 [Baby Inspector]
---------------------------
diff --git a/platform/macosx/Info-Framework.plist b/platform/macosx/Info-Framework.plist
index 2bdfccf99..9ac7b9f46 100644
--- a/platform/macosx/Info-Framework.plist
+++ b/platform/macosx/Info-Framework.plist
@@ -17,11 +17,11 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.9.0
+ 0.9.1
CFBundleSignature
LoVe
CFBundleVersion
- 0.9.0
+ 0.9.1
NSPrincipalClass
diff --git a/platform/macosx/love-Info.plist b/platform/macosx/love-Info.plist
index b14f6022a..c7585e930 100644
--- a/platform/macosx/love-Info.plist
+++ b/platform/macosx/love-Info.plist
@@ -46,7 +46,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.9.0
+ 0.9.1
CFBundleSignature
LoVe
LSApplicationCategoryType
diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj
index dedef2bf8..84e5457de 100644
--- a/platform/macosx/love-framework.xcodeproj/project.pbxproj
+++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj
@@ -289,6 +289,7 @@
FAC86E641724552C00EED715 /* wrap_Quad.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E621724552C00EED715 /* wrap_Quad.h */; };
FAC86E6B1724555D00EED715 /* Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC86E671724555D00EED715 /* Quad.cpp */; };
FAC86E6C1724555D00EED715 /* Quad.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC86E681724555D00EED715 /* Quad.h */; };
+ FADD58DD18C30367005FC3BF /* FormatHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FADD58DC18C30367005FC3BF /* FormatHandler.cpp */; };
FAE010DB170DDE99006F29D0 /* ddsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010D8170DDE99006F29D0 /* ddsinfo.h */; };
FAE010DC170DDE99006F29D0 /* ddsparse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE010D9170DDE99006F29D0 /* ddsparse.cpp */; };
FAE010DD170DDE99006F29D0 /* ddsparse.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010DA170DDE99006F29D0 /* ddsparse.h */; };
@@ -847,6 +848,7 @@
FAC86E621724552C00EED715 /* wrap_Quad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Quad.h; sourceTree = ""; };
FAC86E671724555D00EED715 /* Quad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Quad.cpp; sourceTree = ""; };
FAC86E681724555D00EED715 /* Quad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Quad.h; sourceTree = ""; };
+ FADD58DC18C30367005FC3BF /* FormatHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatHandler.cpp; sourceTree = ""; };
FAE010D8170DDE99006F29D0 /* ddsinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsinfo.h; sourceTree = ""; };
FAE010D9170DDE99006F29D0 /* ddsparse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsparse.cpp; sourceTree = ""; };
FAE010DA170DDE99006F29D0 /* ddsparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsparse.h; sourceTree = ""; };
@@ -1088,6 +1090,7 @@
FAE010DF170DE25E006F29D0 /* ddsHandler.h */,
1AA7781A230065F346E2313A /* DevilHandler.cpp */,
283342E174613897621A43F1 /* DevilHandler.h */,
+ FADD58DC18C30367005FC3BF /* FormatHandler.cpp */,
FA0CDE3B1710F9A50056E8D7 /* FormatHandler.h */,
505F23A73BFE250833D650E4 /* Image.cpp */,
68616BD516DB124312B47EB3 /* Image.h */,
@@ -2045,7 +2048,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0500;
+ LastUpgradeCheck = 0510;
};
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "love-framework" */;
compatibilityVersion = "Xcode 3.2";
@@ -2267,6 +2270,7 @@
FA08F66816C7548200F007B5 /* wrap_WheelJoint.cpp in Sources */,
FA08F66916C7548200F007B5 /* wrap_World.cpp in Sources */,
FA08F66A16C7549200F007B5 /* Sound.cpp in Sources */,
+ FADD58DD18C30367005FC3BF /* FormatHandler.cpp in Sources */,
FA08F66B16C7549200F007B5 /* SoundData.cpp in Sources */,
FA08F66C16C7549200F007B5 /* wrap_Decoder.cpp in Sources */,
FA08F66D16C7549200F007B5 /* wrap_Sound.cpp in Sources */,
@@ -2407,6 +2411,66 @@
};
name = Debug;
};
+ FA5326C4189719C700F7BBF4 /* Distribution */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_ENABLE_MODULES = YES;
+ DEAD_CODE_STRIPPING = YES;
+ FRAMEWORK_SEARCH_PATHS = /Library/Frameworks;
+ GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_PREPROCESSOR_DEFINITIONS = LOVE_MACOSX_USE_FRAMEWORKS;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "\"$(SRCROOT)/../../src\"",
+ "\"$(SRCROOT)/../../src/libraries\"",
+ "\"$(SRCROOT)/../../src/modules\"",
+ "\"$(SRCROOT)/../../src/libraries/enet/libenet/include\"",
+ /Library/Frameworks/FreeType.framework/Headers,
+ /Library/Frameworks/Lua.framework/Headers,
+ /Library/Frameworks/SDL2.framework/Headers,
+ );
+ LD_RUNPATH_SEARCH_PATHS = "@rpath";
+ LIBRARY_SEARCH_PATHS = "";
+ LLVM_LTO = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = NO;
+ USE_HEADERMAP = NO;
+ WARNING_CFLAGS = "-Wall";
+ };
+ name = Distribution;
+ };
+ FA5326C5189719C700F7BBF4 /* Distribution */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_MODULES = NO;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DYLIB_COMPATIBILITY_VERSION = 9.0;
+ DYLIB_CURRENT_VERSION = 9.0;
+ FRAMEWORK_VERSION = A;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ INFOPLIST_FILE = "Info-Framework.plist";
+ LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PATH)";
+ OTHER_LDFLAGS = (
+ "-undefined",
+ dynamic_lookup,
+ );
+ PRODUCT_NAME = love;
+ SKIP_INSTALL = YES;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Distribution;
+ };
FA577AC016C7507900860150 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -2464,6 +2528,7 @@
buildConfigurations = (
64274E785071353E1A1D0D4B /* Debug */,
10D5479E63C26BB35EB5482E /* Release */,
+ FA5326C4189719C700F7BBF4 /* Distribution */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
@@ -2473,6 +2538,7 @@
buildConfigurations = (
FA577AC016C7507900860150 /* Debug */,
FA577AC116C7507900860150 /* Release */,
+ FA5326C5189719C700F7BBF4 /* Distribution */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
diff --git a/platform/macosx/love.xcodeproj/project.pbxproj b/platform/macosx/love.xcodeproj/project.pbxproj
index 9c4739788..ab34a46bf 100644
--- a/platform/macosx/love.xcodeproj/project.pbxproj
+++ b/platform/macosx/love.xcodeproj/project.pbxproj
@@ -198,7 +198,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0500;
+ LastUpgradeCheck = 0510;
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "love" */;
compatibilityVersion = "Xcode 3.2";
@@ -402,6 +402,79 @@
};
name = Release;
};
+ FA5326C618971A0900F7BBF4 /* Distribution */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_ENABLE_MODULES = YES;
+ DEPLOYMENT_POSTPROCESSING = NO;
+ FRAMEWORK_SEARCH_PATHS = /Library/Frameworks;
+ GCC_INPUT_FILETYPE = automatic;
+ GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_PREPROCESSOR_DEFINITIONS = LOVE_MACOSX_USE_FRAMEWORKS;
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = NO;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+ GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = NO;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = NO;
+ GCC_WARN_MISSING_PARENTHESES = NO;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+ GCC_WARN_PEDANTIC = NO;
+ GCC_WARN_SHADOW = NO;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO;
+ GCC_WARN_UNUSED_PARAMETER = NO;
+ GCC_WARN_UNUSED_VALUE = NO;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "\"$(SRCROOT)/../../src\"",
+ "\"$(SRCROOT)/../../src/libraries\"",
+ "\"$(SRCROOT)/../../src/modules\"",
+ /Library/Frameworks/Lua.framework/Headers,
+ /Library/Frameworks/SDL2.framework/Headers,
+ );
+ INFOPLIST_FILE = "love-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
+ LLVM_LTO = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_LDFLAGS = "";
+ "OTHER_LDFLAGS[arch=x86_64]" = (
+ "-pagezero_size",
+ 10000,
+ "-image_base",
+ 100000000,
+ );
+ PRODUCT_NAME = love;
+ SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
+ WARNING_CFLAGS = (
+ "-Wall",
+ "-W",
+ );
+ };
+ name = Distribution;
+ };
+ FA5326C718971A0900F7BBF4 /* Distribution */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/build/Release\"",
+ "\"$(SRCROOT)/build/Debug\"",
+ );
+ INSTALL_PATH = /Applications;
+ PRODUCT_NAME = love;
+ };
+ name = Distribution;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -410,6 +483,7 @@
buildConfigurations = (
C01FCF4B08A954540054247B /* Debug */,
C01FCF4C08A954540054247B /* Release */,
+ FA5326C718971A0900F7BBF4 /* Distribution */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
@@ -419,6 +493,7 @@
buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,
C01FCF5008A954540054247B /* Release */,
+ FA5326C618971A0900F7BBF4 /* Distribution */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
diff --git a/platform/unix/debian/love.install b/platform/unix/debian/love.install
index 487155e20..ac4c7a440 100644
--- a/platform/unix/debian/love.install
+++ b/platform/unix/debian/love.install
@@ -1 +1,6 @@
usr/bin/love
+usr/share/man/man1/love.1
+usr/share/pixmaps/love.svg
+usr/share/mime/packages/love.xml
+usr/share/icons/hicolor/scalable/mimetypes/application-x-love-game.svg
+usr/share/applications/love.desktop
diff --git a/platform/unix/love.1 b/platform/unix/love.1
index 0abaa5577..539cf9a9c 100644
--- a/platform/unix/love.1
+++ b/platform/unix/love.1
@@ -1,4 +1,5 @@
.\" (c) 2008-2011 Miriam Ruiz
+.\" (c) 2013 Bart van Strien
.\"
.\" This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damagesarising from the use of this software.
.\"
@@ -11,16 +12,25 @@
.\" 3. This notice may not be removed or altered from any source distribution.
.\"
.\" Modifications:
-.\" - Update version to 0.9 and remove reference to doc dir - Bart van Strien, 2013
+.\" - Update version to 0.9 and remove reference to doc dir
+.\" - Add fused and version flags
+
.TH "LÖVE" "1" "0.9" "" ""
.SH "NAME"
love \- 2D game development framework
+
.SH "SYNOPSIS"
.B love
-<\fIgame.love\fR>
+[--fused] <\fIgame.love\fR>
+.PP
+.B love
+--version
+.PP
+
.SH "DESCRIPTION"
LÖVE was created to be a user\-friendly engine in which simple (or complicated) games could be made without having extensive knowledge of system or graphics functions and without having to dedicate time towards developing the same engine features time and time again.
.P
Developed with cross\-platform implementation in mind, it utilizes the latest open source libraries to deliver a similar game experience, independent of operating system. By relying on the Lua scripting language for game\-specific programming, it allows even the novice game creator to quickly and efficiently develop an idea into a fully working game.
+
.SH "SEE ALSO"
You can find more information at \fIhttp://love2d.org/\fR
diff --git a/src/common/Data.h b/src/common/Data.h
index ea31e69e7..ffea71cf9 100644
--- a/src/common/Data.h
+++ b/src/common/Data.h
@@ -38,7 +38,7 @@ public:
/**
* Destructor.
**/
- virtual ~Data() {};
+ virtual ~Data() {}
/**
* Gets a pointer to the data. This pointer will obviously not
diff --git a/src/common/Memoizer.cpp b/src/common/Memoizer.cpp
index dcc8e5df2..8d6ec7d4f 100644
--- a/src/common/Memoizer.cpp
+++ b/src/common/Memoizer.cpp
@@ -38,8 +38,12 @@ void Memoizer::remove(void *key)
void *Memoizer::find(void *key)
{
- if (objectMap.count(key)) return objectMap[key];
- return NULL;
+ auto it = objectMap.find(key);
+
+ if (it != objectMap.end())
+ return it->second;
+ else
+ return nullptr;
}
} // love
diff --git a/src/common/Reference.cpp b/src/common/Reference.cpp
index 38e28e099..d2ea05774 100644
--- a/src/common/Reference.cpp
+++ b/src/common/Reference.cpp
@@ -26,7 +26,7 @@ namespace love
const char REFERENCE_TABLE_NAME[] = "love-references";
Reference::Reference()
- : L(0)
+ : L(nullptr)
, idx(LUA_REFNIL)
{
}
@@ -64,21 +64,31 @@ void Reference::unref()
}
}
-void Reference::push()
+void Reference::push(lua_State *newL)
{
if (idx != LUA_REFNIL)
{
- luax_insist(L, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
- lua_rawgeti(L, -1, idx);
- lua_remove(L, -2);
+ luax_insist(newL, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
+ lua_rawgeti(newL, -1, idx);
+ lua_remove(newL, -2);
}
else
- lua_pushnil(L);
+ lua_pushnil(newL);
}
-lua_State *Reference::getL()
+void Reference::push()
+{
+ push(L);
+}
+
+lua_State *Reference::getL() const
{
return L;
}
+void Reference::setL(lua_State *newL)
+{
+ L = newL;
+}
+
} // love
diff --git a/src/common/Reference.h b/src/common/Reference.h
index 5d7341b20..eb8e8b288 100644
--- a/src/common/Reference.h
+++ b/src/common/Reference.h
@@ -63,6 +63,14 @@ public:
**/
void unref();
+ /**
+ * Pushes the referred value onto the stack of a different coroutine
+ * in the same main Lua state.
+ * THIS SHOULD NOT BE USED FOR DIFFERENT LUA STATES (created with
+ * luaL_newstate)! Only with different coroutines!
+ **/
+ void push(lua_State *newL);
+
/**
* Pushes the referred value onto the stack.
**/
@@ -72,7 +80,15 @@ public:
* Gets the Lua state associated with this
* reference.
**/
- lua_State *getL();
+ lua_State *getL() const;
+
+ /**
+ * Associates a new Lua state with this reference.
+ * THIS IS DANGEROUS! It is only designed to be
+ * used with different coroutines from the same
+ * main Lua state!
+ **/
+ void setL(lua_State *newL);
private:
diff --git a/src/common/Vector.cpp b/src/common/Vector.cpp
index 8e0ae515b..c2d37869d 100644
--- a/src/common/Vector.cpp
+++ b/src/common/Vector.cpp
@@ -23,4 +23,4 @@
namespace love
{
// Implementation in header.
-}
\ No newline at end of file
+}
diff --git a/src/common/b64.h b/src/common/b64.h
index 99685cdac..55fe47dea 100644
--- a/src/common/b64.h
+++ b/src/common/b64.h
@@ -38,4 +38,4 @@ char *b64_decode(const char *src, int slen, int &size);
} // love
-#endif // LOVE_B64_H
\ No newline at end of file
+#endif // LOVE_B64_H
diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp
index 55c216adb..e4da8991a 100644
--- a/src/common/runtime.cpp
+++ b/src/common/runtime.cpp
@@ -464,7 +464,7 @@ void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *dat
bool luax_istype(lua_State *L, int idx, love::bits type)
{
- if (lua_isuserdata(L, idx) == 0)
+ if (lua_type(L, idx) != LUA_TUSERDATA)
return false;
return ((((Proxy *)lua_touserdata(L, idx))->flags & type) == type);
diff --git a/src/common/runtime.h b/src/common/runtime.h
index 8f99f259f..de9c6fbde 100644
--- a/src/common/runtime.h
+++ b/src/common/runtime.h
@@ -401,7 +401,7 @@ extern "C" { // Also called from luasocket
template
T *luax_checktype(lua_State *L, int idx, const char *name, love::bits type)
{
- if (lua_isuserdata(L, idx) == 0)
+ if (lua_type(L, idx) != LUA_TUSERDATA)
luax_typerror(L, idx, name);
Proxy *u = (Proxy *)lua_touserdata(L, idx);
diff --git a/src/common/utf8.h b/src/common/utf8.h
index 6f0d78ef1..9a2c51e9b 100644
--- a/src/common/utf8.h
+++ b/src/common/utf8.h
@@ -45,4 +45,4 @@ void replace_char(std::string &str, char find, char replace);
} // love
-#endif // LOVE_WINDOWS
\ No newline at end of file
+#endif // LOVE_WINDOWS
diff --git a/src/common/version.h b/src/common/version.h
index d8798f9dc..5e3e15f72 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -27,9 +27,9 @@ namespace love
// Version stuff.
const int VERSION_MAJOR = 0;
const int VERSION_MINOR = 9;
-const int VERSION_REV = 0;
-const char *VERSION = "0.9.0";
-const char *VERSION_COMPATIBILITY[] = { VERSION, 0 };
+const int VERSION_REV = 1;
+const char *VERSION = "0.9.1";
+const char *VERSION_COMPATIBILITY[] = { VERSION, "0.9.0", 0 };
const char *VERSION_CODENAME = "Baby Inspector";
} // love
diff --git a/src/libraries/ddsparse/ddsparse.cpp b/src/libraries/ddsparse/ddsparse.cpp
index 590d665ce..f6fe62bcc 100644
--- a/src/libraries/ddsparse/ddsparse.cpp
+++ b/src/libraries/ddsparse/ddsparse.cpp
@@ -237,36 +237,37 @@ size_t Parser::getMipmapCount() const
size_t Parser::parseImageSize(Format fmt, int width, int height) const
{
- size_t size = 0;
+ size_t numBlocksWide = 0;
+ size_t numBlocksHigh = 0;
+ size_t numBytesPerBlock = 0;
switch (fmt)
{
case FORMAT_DXT1:
+ case FORMAT_BC4:
+ case FORMAT_BC4s:
+ numBytesPerBlock = 8;
+ break;
case FORMAT_DXT3:
case FORMAT_DXT5:
case FORMAT_BC5s:
case FORMAT_BC5:
+ case FORMAT_BC6H:
case FORMAT_BC7:
case FORMAT_BC7srgb:
- {
- int numBlocksWide = 0;
- if (width > 0)
- numBlocksWide = std::max(1, (width + 3) / 4);
-
- int numBlocksHigh = 0;
- if (height > 0)
- numBlocksHigh = std::max(1, (height + 3) / 4);
-
- int numBytesPerBlock = (fmt == FORMAT_DXT1 ? 8 : 16);
-
- size = numBlocksWide * numBytesPerBlock * numBlocksHigh;
- }
+ numBytesPerBlock = 16;
break;
default:
break;
}
- return size;
+ if (width > 0)
+ numBlocksWide = std::max(1, (width + 3) / 4);
+
+ if (height > 0)
+ numBlocksHigh = std::max(1, (height + 3) / 4);
+
+ return numBlocksWide * numBytesPerBlock * numBlocksHigh;
}
bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int w, int h, int mips)
diff --git a/src/libraries/ddsparse/ddsparse.h b/src/libraries/ddsparse/ddsparse.h
index 82c2c41cc..6ab659347 100644
--- a/src/libraries/ddsparse/ddsparse.h
+++ b/src/libraries/ddsparse/ddsparse.h
@@ -60,7 +60,7 @@ struct Image
const uint8_t *data;
Image() : width(0), height(0), dataSize(0), data(0)
- {};
+ {}
};
/**
diff --git a/src/libraries/enet/enet.cpp b/src/libraries/enet/enet.cpp
index 836c166c6..34e215c78 100644
--- a/src/libraries/enet/enet.cpp
+++ b/src/libraries/enet/enet.cpp
@@ -716,10 +716,6 @@ static const struct luaL_Reg enet_peer_funcs [] = {
{NULL, NULL}
};
-static const struct luaL_Reg enet_event_funcs [] = {
- {NULL, NULL}
-};
-
int luaopen_enet(lua_State *l) {
enet_initialize();
atexit(enet_deinitialize);
diff --git a/src/libraries/luasocket/libluasocket/lua.h b/src/libraries/luasocket/libluasocket/lua.h
index e97bc2ac2..a280df842 100644
--- a/src/libraries/luasocket/libluasocket/lua.h
+++ b/src/libraries/luasocket/libluasocket/lua.h
@@ -1,3 +1,6 @@
+#ifndef LUA_WRAP_H
+#define LUA_WRAP_H
+
#define LUA_COMPAT_ALL
#include
#include
@@ -10,3 +13,5 @@
extern int luax_typerror(lua_State *L, int narg, const char *type);
#endif
+
+#endif // LUA_WRAP_H
diff --git a/src/modules/audio/Audio.h b/src/modules/audio/Audio.h
index b7c192577..9a8ca863c 100644
--- a/src/modules/audio/Audio.h
+++ b/src/modules/audio/Audio.h
@@ -67,7 +67,7 @@ public:
/**
* Destructor.
**/
- virtual ~Audio() {};
+ virtual ~Audio() {}
virtual Source *newSource(love::sound::Decoder *decoder) = 0;
virtual Source *newSource(love::sound::SoundData *soundData) = 0;
@@ -88,7 +88,7 @@ public:
* Play the specified Source.
* @param source The Source to play.
**/
- virtual void play(Source *source) = 0;
+ virtual bool play(Source *source) = 0;
/**
* Stops playback on the specified source.
diff --git a/src/modules/audio/Source.h b/src/modules/audio/Source.h
index d074e8706..d5cf86d7d 100644
--- a/src/modules/audio/Source.h
+++ b/src/modules/audio/Source.h
@@ -53,7 +53,7 @@ public:
virtual Source *clone() = 0;
- virtual void play() = 0;
+ virtual bool play() = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
diff --git a/src/modules/audio/null/Audio.cpp b/src/modules/audio/null/Audio.cpp
index 2e5031ae1..6b6fd3f93 100644
--- a/src/modules/audio/null/Audio.cpp
+++ b/src/modules/audio/null/Audio.cpp
@@ -61,12 +61,9 @@ int Audio::getMaxSources() const
return 0;
}
-void Audio::play(love::audio::Source *)
-{
-}
-
-void Audio::play()
+bool Audio::play(love::audio::Source *)
{
+ return false;
}
void Audio::stop(love::audio::Source *)
diff --git a/src/modules/audio/null/Audio.h b/src/modules/audio/null/Audio.h
index 3f571da67..372f756c5 100644
--- a/src/modules/audio/null/Audio.h
+++ b/src/modules/audio/null/Audio.h
@@ -48,8 +48,7 @@ public:
love::audio::Source *newSource(love::sound::SoundData *soundData);
int getSourceCount() const;
int getMaxSources() const;
- void play(love::audio::Source *source);
- void play();
+ bool play(love::audio::Source *source);
void stop(love::audio::Source *source);
void stop();
void pause(love::audio::Source *source);
diff --git a/src/modules/audio/null/Source.cpp b/src/modules/audio/null/Source.cpp
index ce1ec7f5f..caa212374 100644
--- a/src/modules/audio/null/Source.cpp
+++ b/src/modules/audio/null/Source.cpp
@@ -42,8 +42,9 @@ love::audio::Source *Source::clone()
return this;
}
-void Source::play()
+bool Source::play()
{
+ return false;
}
void Source::stop()
diff --git a/src/modules/audio/null/Source.h b/src/modules/audio/null/Source.h
index 303eb879c..0a5c5253d 100644
--- a/src/modules/audio/null/Source.h
+++ b/src/modules/audio/null/Source.h
@@ -39,7 +39,7 @@ public:
virtual ~Source();
virtual love::audio::Source *clone();
- virtual void play();
+ virtual bool play();
virtual void stop();
virtual void pause();
virtual void resume();
diff --git a/src/modules/audio/openal/Audio.cpp b/src/modules/audio/openal/Audio.cpp
index 07ce2959d..c6af9be19 100644
--- a/src/modules/audio/openal/Audio.cpp
+++ b/src/modules/audio/openal/Audio.cpp
@@ -69,22 +69,25 @@ void Audio::PoolThread::setFinish()
}
Audio::Audio()
- : distanceModel(DISTANCE_INVERSE_CLAMPED)
+ : device(nullptr)
+ , capture(nullptr)
+ , context(nullptr)
+ , pool(nullptr)
+ , poolThread(nullptr)
+ , distanceModel(DISTANCE_INVERSE_CLAMPED)
{
- // Passing zero for default device.
- device = alcOpenDevice(0);
+ // Passing null for default device.
+ device = alcOpenDevice(nullptr);
- if (device == 0)
+ if (device == nullptr)
throw love::Exception("Could not open device.");
- context = alcCreateContext(device, 0);
+ context = alcCreateContext(device, nullptr);
- if (context == 0)
+ if (context == nullptr)
throw love::Exception("Could not create context.");
- alcMakeContextCurrent(context);
-
- if (alcGetError(device) != ALC_NO_ERROR)
+ if (!alcMakeContextCurrent(context) || alcGetError(device) != ALC_NO_ERROR)
throw love::Exception("Could not make context current.");
/*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
@@ -108,7 +111,18 @@ Audio::Audio()
}*/
// pool must be allocated after AL context.
- pool = new Pool();
+ try
+ {
+ pool = new Pool();
+ }
+ catch (love::Exception &)
+ {
+ alcMakeContextCurrent(nullptr);
+ alcDestroyContext(context);
+ //if (capture) alcCaptureCloseDevice(capture);
+ alcCloseDevice(device);
+ throw;
+ }
poolThread = new PoolThread(pool);
poolThread->start();
@@ -122,7 +136,7 @@ Audio::~Audio()
delete poolThread;
delete pool;
- alcMakeContextCurrent(0);
+ alcMakeContextCurrent(nullptr);
alcDestroyContext(context);
//if (capture) alcCaptureCloseDevice(capture);
alcCloseDevice(device);
@@ -154,9 +168,9 @@ int Audio::getMaxSources() const
return pool->getMaxSources();
}
-void Audio::play(love::audio::Source *source)
+bool Audio::play(love::audio::Source *source)
{
- source->play();
+ return source->play();
}
void Audio::stop(love::audio::Source *source)
@@ -281,7 +295,7 @@ bool Audio::canRecord()
Audio::DistanceModel Audio::getDistanceModel() const
{
- return this->distanceModel;
+ return distanceModel;
}
void Audio::setDistanceModel(DistanceModel distanceModel)
diff --git a/src/modules/audio/openal/Audio.h b/src/modules/audio/openal/Audio.h
index a40494b2a..6e5f50696 100644
--- a/src/modules/audio/openal/Audio.h
+++ b/src/modules/audio/openal/Audio.h
@@ -67,8 +67,7 @@ public:
love::audio::Source *newSource(love::sound::SoundData *soundData);
int getSourceCount() const;
int getMaxSources() const;
- void play(love::audio::Source *source);
- void play();
+ bool play(love::audio::Source *source);
void stop(love::audio::Source *source);
void stop();
void pause(love::audio::Source *source);
diff --git a/src/modules/audio/openal/Pool.cpp b/src/modules/audio/openal/Pool.cpp
index f3d74a91a..8d239f4d7 100644
--- a/src/modules/audio/openal/Pool.cpp
+++ b/src/modules/audio/openal/Pool.cpp
@@ -30,23 +30,45 @@ namespace openal
{
Pool::Pool()
+ : sources()
+ , totalSources(0)
+ , mutex(nullptr)
{
+ // Clear errors.
+ alGetError();
+
// Generate sources.
- alGenSources(NUM_SOURCES, sources);
+ for (int i = 0; i < MAX_SOURCES; i++)
+ {
+ alGenSources(1, &sources[i]);
+
+ // We might hit an implementation-dependent limit on the total number
+ // of sources before reaching MAX_SOURCES.
+ if (alGetError() != AL_NO_ERROR)
+ break;
+
+ totalSources++;
+ }
+
+ if (totalSources < 4)
+ throw love::Exception("Could not generate sources.");
// Create the mutex.
mutex = thread::newMutex();
- if (alGetError() != AL_NO_ERROR)
- throw love::Exception("Could not generate sources.");
+ ALboolean hasext = alIsExtensionPresent("AL_SOFT_direct_channels");
// Make all sources available initially.
- for (int i = 0; i < NUM_SOURCES; i++)
+ for (int i = 0; i < totalSources; i++)
{
-#ifdef AL_DIRECT_CHANNELS_SOFT
- // Bypassing virtualization of speakers for multi-channel sources in OpenAL Soft.
- alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
+#ifdef AL_SOFT_direct_channels
+ if (hasext)
+ {
+ // Bypass virtualization of speakers for multi-channel sources in OpenAL Soft.
+ alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
+ }
#endif
+
available.push(sources[i]);
}
}
@@ -58,7 +80,7 @@ Pool::~Pool()
delete mutex;
// Free all sources.
- alDeleteSources(NUM_SOURCES, sources);
+ alDeleteSources(totalSources, sources);
}
bool Pool::isAvailable() const
@@ -113,7 +135,7 @@ int Pool::getSourceCount() const
int Pool::getMaxSources() const
{
- return NUM_SOURCES;
+ return totalSources;
}
bool Pool::play(Source *source, ALuint &out)
@@ -141,9 +163,7 @@ bool Pool::play(Source *source, ALuint &out)
source->retain();
- source->playAtomic();
-
- ok = true;
+ ok = source->playAtomic();
}
else
{
diff --git a/src/modules/audio/openal/Pool.h b/src/modules/audio/openal/Pool.h
index 46353e759..f0896ea97 100644
--- a/src/modules/audio/openal/Pool.h
+++ b/src/modules/audio/openal/Pool.h
@@ -36,6 +36,7 @@
#ifdef LOVE_MACOSX_USE_FRAMEWORKS
#include
#include
+#include
#else
#include
#include
@@ -99,11 +100,15 @@ private:
bool findSource(Source *source, ALuint &out);
bool removeSource(Source *source);
- // Number of OpenAL sources.
- static const int NUM_SOURCES = 64;
+
+ // Maximum possible number of OpenAL sources the pool attempts to generate.
+ static const int MAX_SOURCES = 64;
// OpenAL sources
- ALuint sources[NUM_SOURCES];
+ ALuint sources[MAX_SOURCES];
+
+ // Total number of created sources in the pool.
+ int totalSources;
// A queue of available sources.
std::queue available;
diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp
index a9a38b139..877a35aeb 100644
--- a/src/modules/audio/openal/Source.cpp
+++ b/src/modules/audio/openal/Source.cpp
@@ -165,15 +165,16 @@ love::audio::Source *Source::clone()
return new Source(*this);
}
-void Source::play()
+bool Source::play()
{
if (valid && paused)
{
pool->resume(this);
- return;
+ return true;
}
valid = pool->play(this, source);
+ return valid;
}
void Source::stop()
@@ -512,7 +513,7 @@ bool Source::isLooping() const
return looping;
}
-void Source::playAtomic()
+bool Source::playAtomic()
{
if (type == TYPE_STATIC)
{
@@ -539,10 +540,19 @@ void Source::playAtomic()
// of the new one.
reset();
+ // Clear errors.
+ alGetError();
+
alSourcePlay(source);
+ // alSourcePlay may fail if the system has reached its limit of simultaneous
+ // playing sources.
+ bool success = alGetError() == AL_NO_ERROR;
+
valid = true; //if it fails it will be set to false again
//but this prevents a horrible, horrible bug
+
+ return success;
}
void Source::stopAtomic()
diff --git a/src/modules/audio/openal/Source.h b/src/modules/audio/openal/Source.h
index bb8bc18e9..a2cc9520c 100644
--- a/src/modules/audio/openal/Source.h
+++ b/src/modules/audio/openal/Source.h
@@ -76,7 +76,7 @@ public:
virtual ~Source();
virtual love::audio::Source *clone();
- virtual void play();
+ virtual bool play();
virtual void stop();
virtual void pause();
virtual void resume();
@@ -117,7 +117,7 @@ public:
virtual float getMaxDistance() const;
virtual int getChannels() const;
- void playAtomic();
+ bool playAtomic();
void stopAtomic();
void pauseAtomic();
void resumeAtomic();
diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp
index 4b8e39969..217c4f98e 100644
--- a/src/modules/audio/wrap_Audio.cpp
+++ b/src/modules/audio/wrap_Audio.cpp
@@ -75,8 +75,8 @@ int w_newSource(lua_State *L)
int w_play(lua_State *L)
{
Source *s = luax_checksource(L, 1);
- instance->play(s);
- return 0;
+ luax_pushboolean(L, instance->play(s));
+ return 1;
}
int w_stop(lua_State *L)
diff --git a/src/modules/audio/wrap_Source.cpp b/src/modules/audio/wrap_Source.cpp
index 44b32a07b..c94ded3b4 100644
--- a/src/modules/audio/wrap_Source.cpp
+++ b/src/modules/audio/wrap_Source.cpp
@@ -44,8 +44,8 @@ int w_Source_clone(lua_State *L)
int w_Source_play(lua_State *L)
{
Source *t = luax_checksource(L, 1);
- t->play();
- return 0;
+ luax_pushboolean(L, t->play());
+ return 1;
}
int w_Source_stop(lua_State *L)
diff --git a/src/modules/event/sdl/Event.cpp b/src/modules/event/sdl/Event.cpp
index ece1f7bfd..425da01fa 100644
--- a/src/modules/event/sdl/Event.cpp
+++ b/src/modules/event/sdl/Event.cpp
@@ -37,6 +37,24 @@ namespace event
namespace sdl
{
+// SDL reports mouse coordinates in the window coordinate system in OS X, but
+// we want them in pixel coordinates (may be different with high-DPI enabled.)
+static void windowToPixelCoords(int *x, int *y)
+{
+ double scale = 1.0;
+
+ window::Window *window = (window::Window *) Module::findInstance("love.window.");
+ if (window != nullptr)
+ scale = window->getPixelScale();
+
+ if (x != nullptr)
+ *x = int(double(*x) * scale);
+
+ if (y != nullptr)
+ *y = int(double(*y) * scale);
+}
+
+
const char *Event::getName() const
{
return "love.event.sdl";
@@ -162,8 +180,11 @@ Message *Event::convert(const SDL_Event &e) const
case SDL_MOUSEBUTTONUP:
if (buttons.find(e.button.button, button) && mouse::Mouse::getConstant(button, txt))
{
- arg1 = new Variant((double) e.button.x);
- arg2 = new Variant((double) e.button.y);
+ int x = e.button.x;
+ int y = e.button.y;
+ windowToPixelCoords(&x, &y);
+ arg1 = new Variant((double) x);
+ arg2 = new Variant((double) y);
arg3 = new Variant(txt, strlen(txt));
msg = new Message((e.type == SDL_MOUSEBUTTONDOWN) ?
"mousepressed" : "mousereleased",
@@ -182,6 +203,7 @@ Message *Event::convert(const SDL_Event &e) const
int mx, my;
SDL_GetMouseState(&mx, &my);
+ windowToPixelCoords(&mx, &my);
arg1 = new Variant((double) mx);
arg2 = new Variant((double) my);
@@ -366,7 +388,7 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
Message *Event::convertWindowEvent(const SDL_Event &e) const
{
Message *msg = 0;
- Variant *arg1, *arg2;
+ Variant *arg1, *arg2, *arg3, *arg4;
window::Window *win = 0;
if (e.type != SDL_WINDOWEVENT)
@@ -402,17 +424,31 @@ Message *Event::convertWindowEvent(const SDL_Event &e) const
win = (window::Window *) Module::findInstance("love.window.");
if (win)
{
+ int px_w = e.window.data1;
+ int px_h = e.window.data2;
+
+#if SDL_VERSION_ATLEAST(2,0,1)
+ SDL_Window *sdlwin = SDL_GetWindowFromID(e.window.windowID);
+ if (sdlwin)
+ SDL_GL_GetDrawableSize(sdlwin, &px_w, &px_h);
+#endif
+
win->onWindowResize(e.window.data1, e.window.data2);
graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
if (gfx)
- gfx->setViewportSize(e.window.data1, e.window.data2);
+ gfx->setViewportSize(px_w, px_h);
+
+ arg1 = new Variant((double) px_w);
+ arg2 = new Variant((double) px_h);
+ arg3 = new Variant((double) e.window.data1);
+ arg4 = new Variant((double) e.window.data2);
+ msg = new Message("resize", arg1, arg2, arg3, arg4);
+ arg1->release();
+ arg2->release();
+ arg3->release();
+ arg4->release();
}
- arg1 = new Variant((double) e.window.data1);
- arg2 = new Variant((double) e.window.data2);
- msg = new Message("resize", arg1, arg2);
- arg1->release();
- arg2->release();
break;
}
@@ -608,6 +644,17 @@ std::map Event::createKeyMap()
k[SDLK_AUDIOPLAY] = Keyboard::KEY_AUDIOPLAY;
k[SDLK_AUDIOMUTE] = Keyboard::KEY_AUDIOMUTE;
k[SDLK_MEDIASELECT] = Keyboard::KEY_MEDIASELECT;
+ k[SDLK_WWW] = Keyboard::KEY_WWW;
+ k[SDLK_MAIL] = Keyboard::KEY_MAIL;
+ k[SDLK_CALCULATOR] = Keyboard::KEY_CALCULATOR;
+ k[SDLK_COMPUTER] = Keyboard::KEY_COMPUTER;
+ k[SDLK_AC_SEARCH] = Keyboard::KEY_APP_SEARCH;
+ k[SDLK_AC_HOME] = Keyboard::KEY_APP_HOME;
+ k[SDLK_AC_BACK] = Keyboard::KEY_APP_BACK;
+ k[SDLK_AC_FORWARD] = Keyboard::KEY_APP_FORWARD;
+ k[SDLK_AC_STOP] = Keyboard::KEY_APP_STOP;
+ k[SDLK_AC_REFRESH] = Keyboard::KEY_APP_REFRESH;
+ k[SDLK_AC_BOOKMARKS] = Keyboard::KEY_APP_BOOKMARKS;
k[SDLK_BRIGHTNESSDOWN] = Keyboard::KEY_BRIGHTNESSDOWN;
k[SDLK_BRIGHTNESSUP] = Keyboard::KEY_BRIGHTNESSUP;
diff --git a/src/modules/font/Font.h b/src/modules/font/Font.h
index dacde0348..a92b88efc 100644
--- a/src/modules/font/Font.h
+++ b/src/modules/font/Font.h
@@ -54,4 +54,4 @@ public:
} // font
} // love
-#endif // LOVE_FONT_FONT_H
\ No newline at end of file
+#endif // LOVE_FONT_FONT_H
diff --git a/src/modules/font/GlyphData.h b/src/modules/font/GlyphData.h
index 59aa1200b..6144dcb9b 100644
--- a/src/modules/font/GlyphData.h
+++ b/src/modules/font/GlyphData.h
@@ -46,7 +46,6 @@ struct GlyphMetrics
int advance;
int bearingX;
int bearingY;
- int spacing;
};
/**
diff --git a/src/modules/font/ImageRasterizer.h b/src/modules/font/ImageRasterizer.h
index 5c7e9e8f6..482d442c6 100644
--- a/src/modules/font/ImageRasterizer.h
+++ b/src/modules/font/ImageRasterizer.h
@@ -79,4 +79,4 @@ private:
} // font
} // love
-#endif // LOVE_FONT_IMAGE_RASTERIZER_H
\ No newline at end of file
+#endif // LOVE_FONT_IMAGE_RASTERIZER_H
diff --git a/src/modules/font/Rasterizer.cpp b/src/modules/font/Rasterizer.cpp
index 1454f2557..cec9f0bef 100644
--- a/src/modules/font/Rasterizer.cpp
+++ b/src/modules/font/Rasterizer.cpp
@@ -96,4 +96,4 @@ bool Rasterizer::hasGlyphs(const std::string &text) const
}
} // font
-} // love
\ No newline at end of file
+} // love
diff --git a/src/modules/font/Rasterizer.h b/src/modules/font/Rasterizer.h
index a4cd6e5c9..ff1cd22e5 100644
--- a/src/modules/font/Rasterizer.h
+++ b/src/modules/font/Rasterizer.h
@@ -114,4 +114,4 @@ protected:
} // font
} // love
-#endif // LOVE_FONT_RASTERIZER_H
\ No newline at end of file
+#endif // LOVE_FONT_RASTERIZER_H
diff --git a/src/modules/font/freetype/TrueTypeRasterizer.cpp b/src/modules/font/freetype/TrueTypeRasterizer.cpp
index 847793687..e09328f70 100644
--- a/src/modules/font/freetype/TrueTypeRasterizer.cpp
+++ b/src/modules/font/freetype/TrueTypeRasterizer.cpp
@@ -146,4 +146,4 @@ bool TrueTypeRasterizer::hasGlyph(uint32 glyph) const
} // freetype
} // font
-} // love
\ No newline at end of file
+} // love
diff --git a/src/modules/graphics/Drawable.h b/src/modules/graphics/Drawable.h
index aea03b340..a4cd7e2ff 100644
--- a/src/modules/graphics/Drawable.h
+++ b/src/modules/graphics/Drawable.h
@@ -55,7 +55,7 @@ public:
* @param kx Shear along the x-axis.
* @param ky Shear along the y-axis.
**/
- virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
+ virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) = 0;
};
} // graphics
diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp
index 9976ec4fe..9e997c595 100644
--- a/src/modules/graphics/Graphics.cpp
+++ b/src/modules/graphics/Graphics.cpp
@@ -99,6 +99,16 @@ bool Graphics::getConstant(RendererInfo in, const char *&out)
return rendererInfo.find(in, out);
}
+bool Graphics::getConstant(const char *in, SystemLimit &out)
+{
+ return systemLimits.find(in, out);
+}
+
+bool Graphics::getConstant(SystemLimit in, const char *&out)
+{
+ return systemLimits.find(in, out);
+}
+
StringMap::Entry Graphics::drawModeEntries[] =
{
{ "line", Graphics::DRAW_LINE },
@@ -157,6 +167,8 @@ StringMap::Entry Graphics::suppor
{ "mipmap", Graphics::SUPPORT_MIPMAP },
{ "dxt", Graphics::SUPPORT_DXT },
{ "bc5", Graphics::SUPPORT_BC5 },
+ { "instancing", Graphics::SUPPORT_INSTANCING },
+ { "srgb", Graphics::SUPPORT_SRGB },
};
StringMap Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
@@ -171,5 +183,15 @@ StringMap::Entry Graph
StringMap Graphics::rendererInfo(Graphics::rendererInfoEntries, sizeof(Graphics::rendererInfoEntries));
+StringMap::Entry Graphics::systemLimitEntries[] =
+{
+ {"pointsize", Graphics::LIMIT_POINT_SIZE},
+ {"texturesize", Graphics::LIMIT_TEXTURE_SIZE},
+ {"multicanvas", Graphics::LIMIT_MULTI_CANVAS},
+ {"canvasfsaa", Graphics::LIMIT_CANVAS_FSAA},
+};
+
+StringMap Graphics::systemLimits(Graphics::systemLimitEntries, sizeof(Graphics::systemLimitEntries));
+
} // graphics
} // love
diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h
index 3c35de337..b8a0532bf 100644
--- a/src/modules/graphics/Graphics.h
+++ b/src/modules/graphics/Graphics.h
@@ -87,6 +87,8 @@ public:
SUPPORT_MIPMAP,
SUPPORT_DXT,
SUPPORT_BC5,
+ SUPPORT_INSTANCING,
+ SUPPORT_SRGB,
SUPPORT_MAX_ENUM
};
@@ -99,6 +101,15 @@ public:
RENDERER_INFO_MAX_ENUM
};
+ enum SystemLimit
+ {
+ LIMIT_POINT_SIZE,
+ LIMIT_TEXTURE_SIZE,
+ LIMIT_MULTI_CANVAS,
+ LIMIT_CANVAS_FSAA,
+ LIMIT_MAX_ENUM
+ };
+
virtual ~Graphics();
/**
@@ -111,7 +122,7 @@ public:
* @param width The viewport width.
* @param height The viewport height.
**/
- virtual bool setMode(int width, int height) = 0;
+ virtual bool setMode(int width, int height, bool &sRGB) = 0;
/**
* Un-sets the current graphics display mode (uninitializing objects if
@@ -140,6 +151,9 @@ public:
static bool getConstant(const char *in, RendererInfo &out);
static bool getConstant(RendererInfo in, const char *&out);
+ static bool getConstant(const char *in, SystemLimit &out);
+ static bool getConstant(SystemLimit in, const char *&out);
+
private:
static StringMap::Entry drawModeEntries[];
@@ -163,6 +177,9 @@ private:
static StringMap::Entry rendererInfoEntries[];
static StringMap rendererInfo;
+ static StringMap::Entry systemLimitEntries[];
+ static StringMap systemLimits;
+
}; // Graphics
} // graphics
diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp
index 25034a3d0..0a8d85541 100644
--- a/src/modules/graphics/Texture.cpp
+++ b/src/modules/graphics/Texture.cpp
@@ -109,6 +109,16 @@ bool Texture::getConstant(WrapMode in, const char *&out)
return wrapModes.find(in, out);
}
+bool Texture::getConstant(const char *in, Format &out)
+{
+ return formats.find(in, out);
+}
+
+bool Texture::getConstant(Format in, const char *&out)
+{
+ return formats.find(in, out);
+}
+
StringMap::Entry Texture::filterModeEntries[] =
{
{ "linear", Texture::FILTER_LINEAR },
@@ -125,6 +135,15 @@ StringMap::Entry Texture::wrapModeEnt
StringMap Texture::wrapModes(Texture::wrapModeEntries, sizeof(Texture::wrapModeEntries));
+StringMap::Entry Texture::formatEntries[] =
+{
+ {"normal", Texture::FORMAT_NORMAL},
+ {"hdr", Texture::FORMAT_HDR},
+ {"srgb", Texture::FORMAT_SRGB},
+};
+
+StringMap Texture::formats(Texture::formatEntries, sizeof(Texture::formatEntries));
+
} // graphics
} // love
diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h
index e87c432f4..d9c83171e 100644
--- a/src/modules/graphics/Texture.h
+++ b/src/modules/graphics/Texture.h
@@ -55,6 +55,14 @@ public:
FILTER_MAX_ENUM
};
+ enum Format
+ {
+ FORMAT_NORMAL,
+ FORMAT_HDR,
+ FORMAT_SRGB,
+ FORMAT_MAX_ENUM
+ };
+
struct Filter
{
Filter();
@@ -88,7 +96,7 @@ public:
* @param kx Shear along the x-axis.
* @param ky Shear along the y-axis.
**/
- virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
+ virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) = 0;
virtual int getWidth() const;
virtual int getHeight() const;
@@ -111,6 +119,9 @@ public:
static bool getConstant(const char *in, WrapMode &out);
static bool getConstant(WrapMode in, const char *&out);
+ static bool getConstant(const char *in, Format &out);
+ static bool getConstant(Format in, const char *&out);
+
protected:
int width;
@@ -132,6 +143,9 @@ private:
static StringMap::Entry wrapModeEntries[];
static StringMap wrapModes;
+ static StringMap::Entry formatEntries[];
+ static StringMap formats;
+
}; // Texture
} // graphics
diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp
index 855830dd1..58ee616c4 100644
--- a/src/modules/graphics/opengl/Canvas.cpp
+++ b/src/modules/graphics/opengl/Canvas.cpp
@@ -55,10 +55,25 @@ struct FramebufferStrategy
/**
* @param[in] width Width of the stencil buffer
* @param[in] height Height of the stencil buffer
+ * @param[in] samples Number of samples to use
* @param[out] stencil Name for stencil buffer
* @return Whether the stencil buffer was successfully created
**/
- virtual bool createStencil(int, int, GLuint &)
+ virtual bool createStencil(int, int, int, GLuint &)
+ {
+ return false;
+ }
+
+ /// Create a MSAA renderbuffer and attach it to the active FBO.
+ /**
+ * @param[in] width Width of the MSAA buffer
+ * @param[in] height Height of the MSAA buffer
+ * @param[inout] samples Number of samples to use
+ * @param[in] internalformat The internal format to use for the buffer
+ * @param[out] buffer Name for the MSAA buffer
+ * @return Whether the MSAA buffer was successfully created and attached
+ **/
+ virtual bool createMSAABuffer(int, int, int &, GLenum, GLuint &)
{
return false;
}
@@ -68,7 +83,7 @@ struct FramebufferStrategy
* @param[in] framebuffer Framebuffer name
* @param[in] depth_stencil Name for packed depth and stencil buffer
*/
- virtual void deleteFBO(GLuint, GLuint) {}
+ virtual void deleteFBO(GLuint, GLuint, GLuint) {}
virtual void bindFBO(GLuint) {}
/// attach additional canvases to the active framebuffer for rendering
@@ -93,8 +108,11 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, texture, 0);
+ if (texture != 0)
+ {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture, 0);
+ }
// check status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -104,27 +122,62 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
return status;
}
- virtual bool createStencil(int width, int height, GLuint &stencil)
+ virtual bool createStencil(int width, int height, int samples, GLuint &stencil)
{
// create combined depth/stencil buffer
glDeleteRenderbuffers(1, &stencil);
glGenRenderbuffers(1, &stencil);
glBindRenderbuffer(GL_RENDERBUFFER, stencil);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+
+ if (samples > 1)
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH_STENCIL, width, height);
+ else
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, stencil);
+ GL_RENDERBUFFER, stencil);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// check status
- return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ glDeleteRenderbuffers(1, &stencil);
+ stencil = 0;
+ return false;
+ }
+
+ return true;
}
- virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
+ virtual bool createMSAABuffer(int width, int height, int &samples, GLenum internalformat, GLuint &buffer)
+ {
+ glGenRenderbuffers(1, &buffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, buffer);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat,
+ width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, buffer);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
+
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ glDeleteRenderbuffers(1, &buffer);
+ buffer = 0;
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint msaa_buffer)
{
if (depth_stencil != 0)
glDeleteRenderbuffers(1, &depth_stencil);
+ if (msaa_buffer != 0)
+ glDeleteRenderbuffers(1, &msaa_buffer);
if (framebuffer != 0)
glDeleteFramebuffers(1, &framebuffer);
}
@@ -189,27 +242,71 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
return status;
}
- virtual bool createStencil(int width, int height, GLuint &stencil)
+ virtual bool createStencil(int width, int height, int samples, GLuint &stencil)
{
// create combined depth/stencil buffer
- glDeleteRenderbuffers(1, &stencil);
+ glDeleteRenderbuffersEXT(1, &stencil);
glGenRenderbuffersEXT(1, &stencil);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
- width, height);
+
+ if (samples > 1)
+ {
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
+ GL_DEPTH_STENCIL, width, height);
+ }
+ else
+ {
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
+ width, height);
+ }
+
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, stencil);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// check status
- return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ glDeleteRenderbuffersEXT(1, &stencil);
+ stencil = 0;
+ return false;
+ }
+
+ return true;
}
- virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
+ virtual bool createMSAABuffer(int width, int height, int &samples, GLenum internalformat, GLuint &buffer)
+ {
+ if (!GLEE_EXT_framebuffer_multisample)
+ return false;
+
+ glGenRenderbuffersEXT(1, &buffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER, buffer);
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
+ internalformat, width, height);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, buffer);
+ glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
+
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ glDeleteRenderbuffersEXT(1, &buffer);
+ buffer = 0;
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint msaa_buffer)
{
if (depth_stencil != 0)
glDeleteRenderbuffersEXT(1, &depth_stencil);
+ if (msaa_buffer != 0)
+ glDeleteRenderbuffersEXT(1, &msaa_buffer);
if (framebuffer != 0)
glDeleteFramebuffersEXT(1, &framebuffer);
}
@@ -254,33 +351,50 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
{
- virtual bool createStencil(int width, int height, GLuint &stencil)
+ virtual bool createStencil(int width, int height, int samples, GLuint &stencil)
{
// create stencil buffer
- glDeleteRenderbuffers(1, &stencil);
+ glDeleteRenderbuffersEXT(1, &stencil);
glGenRenderbuffersEXT(1, &stencil);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
- width, height);
+
+ if (samples > 1)
+ {
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
+ GL_STENCIL_INDEX, width, height);
+ }
+ else
+ {
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
+ width, height);
+ }
+
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, stencil);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// check status
- return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ glDeleteRenderbuffersEXT(1, &stencil);
+ stencil = 0;
+ return false;
+ }
+
+ return true;
}
bool isSupported()
{
GLuint fb = 0, stencil = 0;
GLenum status = createFBO(fb, 0);
- deleteFBO(fb, stencil);
+ deleteFBO(fb, stencil, 0);
return status == GL_FRAMEBUFFER_COMPLETE;
}
};
-FramebufferStrategy *strategy = NULL;
+FramebufferStrategy *strategy = nullptr;
FramebufferStrategy strategyNone;
@@ -290,8 +404,9 @@ FramebufferStrategyPackedEXT strategyPackedEXT;
FramebufferStrategyEXT strategyEXT;
-Canvas *Canvas::current = NULL;
+Canvas *Canvas::current = nullptr;
OpenGL::Viewport Canvas::systemViewport = OpenGL::Viewport();
+bool Canvas::screenHasSRGB = false;
static void getStrategy()
{
@@ -308,14 +423,15 @@ static void getStrategy()
}
}
-static int maxFBOColorAttachments = 0;
-static int maxDrawBuffers = 0;
-
-Canvas::Canvas(int width, int height, TextureType texture_type)
+Canvas::Canvas(int width, int height, Texture::Format format, int fsaa)
: fbo(0)
+ , resolve_fbo(0)
, texture(0)
+ , fsaa_buffer(0)
, depth_stencil(0)
- , texture_type(texture_type)
+ , format(format)
+ , fsaa_samples(fsaa)
+ , fsaa_dirty(false)
{
this->width = width;
this->height = height;
@@ -357,9 +473,50 @@ Canvas::~Canvas()
unloadVolatile();
}
+bool Canvas::createFSAAFBO(GLenum internalformat)
+{
+ // Create our FBO without a texture.
+ status = strategy->createFBO(fbo, 0);
+
+ GLuint previous = 0;
+ if (current != this)
+ {
+ if (current != nullptr)
+ previous = current->fbo;
+
+ strategy->bindFBO(fbo);
+ }
+
+ // Create and attach the MSAA buffer for our FBO.
+ if (strategy->createMSAABuffer(width, height, fsaa_samples, internalformat, fsaa_buffer))
+ status = GL_FRAMEBUFFER_COMPLETE;
+ else
+ status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+
+ // Create the FBO used for the MSAA resolve, and attach the texture.
+ if (status == GL_FRAMEBUFFER_COMPLETE)
+ status = strategy->createFBO(resolve_fbo, texture);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ // Clean up.
+ strategy->deleteFBO(fbo, 0, fsaa_buffer);
+ strategy->deleteFBO(resolve_fbo, 0, 0);
+ fbo = fsaa_buffer = resolve_fbo = 0;
+ fsaa_samples = 0;
+ }
+
+ if (current != this)
+ strategy->bindFBO(previous);
+
+ return status == GL_FRAMEBUFFER_COMPLETE;
+}
+
bool Canvas::loadVolatile()
{
fbo = depth_stencil = texture = 0;
+ resolve_fbo = fsaa_buffer = 0;
+ status = GL_FRAMEBUFFER_COMPLETE;
// glTexImage2D is guaranteed to error in this case.
if (width > gl.getMaxTextureSize() || height > gl.getMaxTextureSize())
@@ -376,13 +533,17 @@ bool Canvas::loadVolatile()
GLint internalformat;
GLenum textype;
- switch (texture_type)
+ switch (format)
{
- case TYPE_HDR:
+ case Texture::FORMAT_HDR:
internalformat = GL_RGBA16F;
textype = GL_FLOAT;
break;
- case TYPE_NORMAL:
+ case Texture::FORMAT_SRGB:
+ internalformat = GL_SRGB8_ALPHA8;
+ textype = GL_UNSIGNED_BYTE;
+ break;
+ case Texture::FORMAT_NORMAL:
default:
internalformat = GL_RGBA8;
textype = GL_UNSIGNED_BYTE;
@@ -406,21 +567,44 @@ bool Canvas::loadVolatile()
return false;
}
- status = strategy->createFBO(fbo, texture);
+ int max_samples = 0;
+ if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object
+ || GLEE_EXT_framebuffer_multisample)
+ {
+ glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+ }
+
+ if (fsaa_samples > max_samples)
+ fsaa_samples = max_samples;
+
+ // Try to create a FSAA FBO if requested.
+ bool fsaasuccess = false;
+ if (fsaa_samples > 1)
+ fsaasuccess = createFSAAFBO(internalformat);
+
+ // On failure (or no requested FSAA), fall back to a regular FBO.
+ if (!fsaasuccess)
+ status = strategy->createFBO(fbo, texture);
+
if (status != GL_FRAMEBUFFER_COMPLETE)
return false;
clear(Color(0, 0, 0, 0));
+
+ fsaa_dirty = (fsaa_buffer != 0);
+
return true;
}
void Canvas::unloadVolatile()
{
- strategy->deleteFBO(fbo, depth_stencil);
+ strategy->deleteFBO(fbo, depth_stencil, fsaa_buffer);
+ strategy->deleteFBO(resolve_fbo, 0, 0);
gl.deleteTexture(texture);
fbo = depth_stencil = texture = 0;
+ resolve_fbo = fsaa_buffer = 0;
for (size_t i = 0; i < attachedCanvases.size(); i++)
attachedCanvases[i]->release();
@@ -428,13 +612,12 @@ void Canvas::unloadVolatile()
attachedCanvases.clear();
}
-void Canvas::drawv(const Matrix &t, const Vertex *v) const
+void Canvas::drawv(const Matrix &t, const Vertex *v)
{
glPushMatrix();
-
glMultMatrixf((const GLfloat *)t.getElements());
- gl.bindTexture(texture);
+ predraw();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -447,11 +630,13 @@ void Canvas::drawv(const Matrix &t, const Vertex *v) const
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
+
+ postdraw();
glPopMatrix();
}
-void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
+void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
{
static Matrix t;
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
@@ -459,7 +644,7 @@ void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, f
drawv(t, vertices);
}
-void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
+void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
{
static Matrix t;
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
@@ -487,8 +672,12 @@ GLuint Canvas::getGLTexture() const
return texture;
}
-void Canvas::predraw() const
+void Canvas::predraw()
{
+ // We need to make sure the texture is up-to-date by resolving the MSAA
+ // buffer (which we render to when the canvas is active) to it.
+ resolveMSAA();
+
gl.bindTexture(texture);
}
@@ -498,12 +687,19 @@ void Canvas::setupGrab()
if (current == this)
return;
- // cleanup after previous fbo
- if (current != NULL)
- current->stopGrab();
+ // cleanup after previous Canvas
+ if (current != nullptr)
+ {
+ systemViewport = current->systemViewport;
+ current->stopGrab(true);
+ }
+ else
+ systemViewport = gl.getViewport();
+
+ // indicate we are using this Canvas.
+ current = this;
// bind the framebuffer object.
- systemViewport = gl.getViewport();
strategy->bindFBO(fbo);
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
@@ -518,8 +714,14 @@ void Canvas::setupGrab()
// Switch back to modelview matrix
glMatrixMode(GL_MODELVIEW);
- // indicate we are using this fbo
- current = this;
+ // Make sure the correct sRGB setting is used when drawing to the canvas.
+ if (format == FORMAT_SRGB)
+ glEnable(GL_FRAMEBUFFER_SRGB);
+ else if (screenHasSRGB)
+ glDisable(GL_FRAMEBUFFER_SRGB);
+
+ if (fsaa_buffer != 0)
+ fsaa_dirty = true;
}
void Canvas::startGrab(const std::vector