Browse Source

Merge remote-tracking branch 'origin/12.0-development' into vulkan

niki 3 years ago
parent
commit
4047cc9d3a

+ 3 - 2
changes.txt

@@ -45,6 +45,7 @@ Released: N/A
 * Added love.keyboard.isModifierActive.
 * Added love.system.getPreferredLocales.
 * Added love.localechanged callback.
+* Added World:getFixturesInArea().
 
 * Changed the default font from Vera size 12 to Noto Sans size 13.
 * Changed the Texture class and implementation to no longer have separate Canvas and Image subclasses.
@@ -165,7 +166,7 @@ Released: 2019-10-27
 * Fixed audio clicks immediately after playing a Source on iOS.
 * Fixed Source:play + Source:stop + Source:play looping the first few ms of sound for streaming Sources on iOS.
 * Fixed Source:play + Source:seek looping the first few ms of sound for streaming Sources on iOS.
-* Fixed occasional pops in streaming sources on iOS. 
+* Fixed occasional pops in streaming sources on iOS.
 * Fixed love.audio.play(sources) to use previously set playback positions on stopped Sources.
 * Fixed Source:setEffect(name, true) and Source:getEffect(name) when the effect has no associated Filter.
 * Fixed love.audio.newSource(filename, "queue") to cause a Lua error.
@@ -437,7 +438,7 @@ Released: 2016-10-31
 
   * Improved performance of Channel methods by roughly 2x in many cases.
   * Improved performance of Shader:send when small numbers of arguments are given.
-  
+
   * Updated love.filesystem.mount to accept a DroppedFile as the first parameter.
   * Updated Shader:send to do type and argument checking based on the specified uniform variable's information instead of the arguments to the function.
   * Updated Shader:send to accept a flat table for matrix uniforms.

+ 30 - 51
src/modules/graphics/Shader.cpp

@@ -89,55 +89,35 @@ static const char render_uniforms[] = R"(
 // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
 // but we can't guarantee that highp is always supported in fragment shaders...
 // We *really* don't want to use mediump for these in vertex shaders though.
+#ifdef LOVE_SPLIT_UNIFORMS_PER_DRAW
+uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[12];
+uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw2[1];
+#else
 uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
+#endif
 
-// These are initialized in love_initializeBuiltinUniforms below. GLSL ES can't
-// do it as an initializer.
-LOVE_HIGHP_OR_MEDIUMP mat4 TransformMatrix;
-LOVE_HIGHP_OR_MEDIUMP mat4 ProjectionMatrix;
-LOVE_HIGHP_OR_MEDIUMP mat3 NormalMatrix;
-
-LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize;
-LOVE_HIGHP_OR_MEDIUMP vec4 ConstantColor;
+// Older GLSL doesn't support preprocessor line continuations...
+#define TransformMatrix mat4(love_UniformsPerDraw[0], love_UniformsPerDraw[1], love_UniformsPerDraw[2], love_UniformsPerDraw[3])
+#define ProjectionMatrix mat4(love_UniformsPerDraw[4], love_UniformsPerDraw[5], love_UniformsPerDraw[6], love_UniformsPerDraw[7])
+#define TransformProjectionMatrix (ProjectionMatrix * TransformMatrix)
 
-LOVE_HIGHP_OR_MEDIUMP float CurrentDPIScale;
+#define NormalMatrix mat3(love_UniformsPerDraw[8].xyz, love_UniformsPerDraw[9].xyz, love_UniformsPerDraw[10].xyz)
 
-LOVE_HIGHP_OR_MEDIUMP float ConstantPointSize;
+#define CurrentDPIScale (love_UniformsPerDraw[8].w)
+#define ConstantPointSize (love_UniformsPerDraw[9].w)
+#define ConstantColor (love_UniformsPerDraw[11])
 
-#define TransformProjectionMatrix (ProjectionMatrix * TransformMatrix)
+#ifdef LOVE_SPLIT_UNIFORMS_PER_DRAW
+#define love_ScreenSize (love_UniformsPerDraw2[0])
+#else
+#define love_ScreenSize (love_UniformsPerDraw[12])
+#endif
 
 // Alternate names
 #define ViewSpaceFromLocal TransformMatrix
 #define ClipSpaceFromView ProjectionMatrix
 #define ClipSpaceFromLocal TransformProjectionMatrix
 #define ViewNormalFromLocal NormalMatrix
-
-void love_initializeBuiltinUniforms() {
-	TransformMatrix = mat4(
-	   love_UniformsPerDraw[0],
-	   love_UniformsPerDraw[1],
-	   love_UniformsPerDraw[2],
-	   love_UniformsPerDraw[3]
-	);
-
-	ProjectionMatrix = mat4(
-	   love_UniformsPerDraw[4],
-	   love_UniformsPerDraw[5],
-	   love_UniformsPerDraw[6],
-	   love_UniformsPerDraw[7]
-	);
-
-	NormalMatrix = mat3(
-	   love_UniformsPerDraw[8].xyz,
-	   love_UniformsPerDraw[9].xyz,
-	   love_UniformsPerDraw[10].xyz
-	);
-
-	CurrentDPIScale = love_UniformsPerDraw[8].w;
-	ConstantPointSize = love_UniformsPerDraw[9].w;
-	love_ScreenSize = love_UniformsPerDraw[11];
-	ConstantColor = love_UniformsPerDraw[12];
-}
 )";
 
 static const char global_functions[] = R"(
@@ -274,7 +254,6 @@ LOVE_IO_LOCATION(1) varying vec4 VaryingColor;
 vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
 
 void main() {
-	love_initializeBuiltinUniforms();
 	VaryingTexCoord = VertexTexCoord;
 	VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor;
 	love_Position = position(ClipSpaceFromLocal, VertexPosition);
@@ -285,7 +264,6 @@ static const char vertex_main_raw[] = R"(
 void vertexmain();
 
 void main() {
-	love_initializeBuiltinUniforms();
 	vertexmain();
 }
 )";
@@ -344,7 +322,6 @@ LOVE_IO_LOCATION(1) varying mediump vec4 VaryingColor;
 vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
 
 void main() {
-	love_initializeBuiltinUniforms();
 	love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord);
 }
 )";
@@ -380,7 +357,6 @@ LOVE_IO_LOCATION(1) varying mediump vec4 VaryingColor;
 void effect();
 
 void main() {
-	love_initializeBuiltinUniforms();
 	effect();
 }
 )";
@@ -389,7 +365,6 @@ static const char pixel_main_raw[] = R"(
 void pixelmain();
 
 void main() {
-	love_initializeBuiltinUniforms();
 	pixelmain();
 }
 )";
@@ -404,7 +379,6 @@ static const char compute_header[] = R"(
 )";
 
 static const char compute_uniforms[] = R"(
-void love_initializeBuiltinUniforms() {}
 )";
 
 static const char compute_functions[] = R"()";
@@ -413,7 +387,6 @@ static const char compute_main[] = R"(
 void computemain();
 
 void main() {
-	love_initializeBuiltinUniforms();
 	computemain();
 }
 )";
@@ -575,7 +548,12 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
 	if (info.usesMRT)
 		ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
 
-	for (const auto& def : options.defines)
+	// Note: backends are expected to handle this situation if highp is ever
+	// conditional in that backend.
+	if (!gfx->getCapabilities().features[Graphics::FEATURE_PIXEL_SHADER_HIGHP])
+		ss << "#define LOVE_SPLIT_UNIFORMS_PER_DRAW 1";
+
+	for (const auto &def : options.defines)
 		ss << "#define " + def.first + " " + def.second + "\n";
 
 	ss << "#define " << stageinfo.name << " " << stageinfo.name << "\n";
@@ -1204,11 +1182,12 @@ static StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM> languages(language
 
 static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry builtinNameEntries[] =
 {
-	{ "MainTex",              Shader::BUILTIN_TEXTURE_MAIN      },
-	{ "love_VideoYChannel",   Shader::BUILTIN_TEXTURE_VIDEO_Y   },
-	{ "love_VideoCbChannel",  Shader::BUILTIN_TEXTURE_VIDEO_CB  },
-	{ "love_VideoCrChannel",  Shader::BUILTIN_TEXTURE_VIDEO_CR  },
-	{ "love_UniformsPerDraw", Shader::BUILTIN_UNIFORMS_PER_DRAW },
+	{ "MainTex",               Shader::BUILTIN_TEXTURE_MAIN        },
+	{ "love_VideoYChannel",    Shader::BUILTIN_TEXTURE_VIDEO_Y     },
+	{ "love_VideoCbChannel",   Shader::BUILTIN_TEXTURE_VIDEO_CB    },
+	{ "love_VideoCrChannel",   Shader::BUILTIN_TEXTURE_VIDEO_CR    },
+	{ "love_UniformsPerDraw",  Shader::BUILTIN_UNIFORMS_PER_DRAW   },
+	{ "love_UniformsPerDraw2", Shader::BUILTIN_UNIFORMS_PER_DRAW_2 },
 };
 
 static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> builtinNames(builtinNameEntries, sizeof(builtinNameEntries));

+ 4 - 1
src/modules/graphics/Shader.h

@@ -64,6 +64,7 @@ public:
 		BUILTIN_TEXTURE_VIDEO_CB,
 		BUILTIN_TEXTURE_VIDEO_CR,
 		BUILTIN_UNIFORMS_PER_DRAW,
+		BUILTIN_UNIFORMS_PER_DRAW_2,
 		BUILTIN_MAX_ENUM
 	};
 
@@ -176,8 +177,10 @@ public:
  		Matrix4 transformMatrix;
  		Matrix4 projectionMatrix;
  		Vector4 normalMatrix[3]; // 3x3 matrix padded to an array of 3 vector4s.
- 		Vector4 screenSizeParams;
  		Colorf constantColor;
+
+		// Pixel shader-centric variables past this point.
+		Vector4 screenSizeParams;
  	};
 
 	// Pointer to currently active Shader.

+ 27 - 3
src/modules/graphics/opengl/Shader.cpp

@@ -46,6 +46,7 @@ static bool isBuffer(Shader::UniformType utype)
 Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
 	: love::graphics::Shader(stages)
 	, program(0)
+	, splitUniformsPerDraw(false)
 	, builtinUniforms()
 	, builtinUniformInfo()
 {
@@ -486,6 +487,11 @@ bool Shader::loadVolatile()
 {
 	OpenGL::TempDebugGroup debuggroup("Shader load");
 
+	// love::graphics::Shader sets up the shader code-side of this.
+	auto gfx = Module::getInstance<love::graphics::Graphics>(Module::M_GRAPHICS);
+	if (gfx != nullptr)
+		splitUniformsPerDraw = gfx->getCapabilities().features[Graphics::FEATURE_PIXEL_SHADER_HIGHP];
+
 	// zero out active texture list
 	textureUnits.clear();
 	textureUnits.push_back(TextureUnit());
@@ -1014,9 +1020,27 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW,
 	data.constantColor = gfx->getColor();
 	gammaCorrectColor(data.constantColor);
 
-	GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
-	if (location >= 0)
-		glUniform4fv(location, 13, (const GLfloat *) &data);
+	// This branch is to avoid always declaring the whole array as highp in the
+	// vertex shader and mediump in the pixel shader for love's default shaders,
+	// on systems that don't support highp in pixel shaders. The default shaders
+	// use the transform matrices in vertex shaders and screen size params in
+	// pixel shaders. If there's a single array containing both and each shader
+	// stage declares a different precision, that's a compile error.
+	if (splitUniformsPerDraw)
+	{
+		GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
+		if (location >= 0)
+			glUniform4fv(location, 12, (const GLfloat *) &data);
+		GLint location2 = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW_2];
+		if (location2 >= 0)
+			glUniform4fv(location2, 1, (const GLfloat *) &data.screenSizeParams);
+	}
+	else
+	{
+		GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW];
+		if (location >= 0)
+			glUniform4fv(location, 13, (const GLfloat *) &data);
+	}
 }
 
 int Shader::getUniformTypeComponents(GLenum type) const

+ 2 - 0
src/modules/graphics/opengl/Shader.h

@@ -112,6 +112,8 @@ private:
 	// volatile
 	GLuint program;
 
+	bool splitUniformsPerDraw;
+
 	// Location values for any built-in uniform variables.
 	GLint builtinUniforms[BUILTIN_MAX_ENUM];
 	UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM];

+ 14 - 10
src/modules/joystick/Joystick.cpp

@@ -58,16 +58,20 @@ STRINGMAP_CLASS_END(Joystick, Joystick::Hat, Joystick::HAT_MAX_ENUM, hat)
 
 STRINGMAP_CLASS_BEGIN(Joystick, Joystick::GamepadType, Joystick::GAMEPAD_TYPE_MAX_ENUM, gamepadType)
 {
-	{ "unknown",    Joystick::GAMEPAD_TYPE_UNKNOWN             },
-	{ "xbox360",    Joystick::GAMEPAD_TYPE_XBOX360             },
-	{ "xboxone",    Joystick::GAMEPAD_TYPE_XBOXONE             },
-	{ "ps3",        Joystick::GAMEPAD_TYPE_PS3                 },
-	{ "ps4",        Joystick::GAMEPAD_TYPE_PS4                 },
-	{ "ps5",        Joystick::GAMEPAD_TYPE_PS5                 },
-	{ "switchpro",  Joystick::GAMEPAD_TYPE_NINTENDO_SWITCH_PRO },
-	{ "amazonluna", Joystick::GAMEPAD_TYPE_AMAZON_LUNA         },
-	{ "stadia",     Joystick::GAMEPAD_TYPE_STADIA              },
-	{ "virtual",    Joystick::GAMEPAD_TYPE_VIRTUAL             },
+	{ "unknown",      Joystick::GAMEPAD_TYPE_UNKNOWN             },
+	{ "xbox360",      Joystick::GAMEPAD_TYPE_XBOX360             },
+	{ "xboxone",      Joystick::GAMEPAD_TYPE_XBOXONE             },
+	{ "ps3",          Joystick::GAMEPAD_TYPE_PS3                 },
+	{ "ps4",          Joystick::GAMEPAD_TYPE_PS4                 },
+	{ "ps5",          Joystick::GAMEPAD_TYPE_PS5                 },
+	{ "switchpro",    Joystick::GAMEPAD_TYPE_NINTENDO_SWITCH_PRO },
+	{ "amazonluna",   Joystick::GAMEPAD_TYPE_AMAZON_LUNA         },
+	{ "stadia",       Joystick::GAMEPAD_TYPE_STADIA              },
+	{ "virtual",      Joystick::GAMEPAD_TYPE_VIRTUAL             },
+	{ "shield",       Joystick::GAMEPAD_TYPE_NVIDIA_SHIELD       },
+	{ "joyconleft",   Joystick::GAMEPAD_TYPE_JOYCON_LEFT         },
+	{ "joyconright",  Joystick::GAMEPAD_TYPE_JOYCON_RIGHT        },
+	{ "joyconpair",   Joystick::GAMEPAD_TYPE_JOYCON_PAIR         },
 }
 STRINGMAP_CLASS_END(Joystick, Joystick::GamepadType, Joystick::GAMEPAD_TYPE_MAX_ENUM, gamepadType)
 

+ 4 - 0
src/modules/joystick/Joystick.h

@@ -68,6 +68,10 @@ public:
 		GAMEPAD_TYPE_AMAZON_LUNA,
 		GAMEPAD_TYPE_STADIA,
 		GAMEPAD_TYPE_VIRTUAL,
+		GAMEPAD_TYPE_NVIDIA_SHIELD,
+		GAMEPAD_TYPE_JOYCON_LEFT,
+		GAMEPAD_TYPE_JOYCON_RIGHT,
+		GAMEPAD_TYPE_JOYCON_PAIR,
 		GAMEPAD_TYPE_MAX_ENUM
 	};
 

+ 7 - 1
src/modules/joystick/sdl/Joystick.cpp

@@ -260,6 +260,12 @@ Joystick::GamepadType Joystick::getGamepadType() const
 #if SDL_VERSION_ATLEAST(2, 0, 16)
 		case SDL_CONTROLLER_TYPE_AMAZON_LUNA: return GAMEPAD_TYPE_AMAZON_LUNA;
 		case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: return GAMEPAD_TYPE_STADIA;
+#endif
+#if SDL_VERSION_ATLEAST(2, 24, 0)
+		case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: return GAMEPAD_TYPE_NVIDIA_SHIELD;
+		case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: return GAMEPAD_TYPE_JOYCON_LEFT;
+		case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: return GAMEPAD_TYPE_JOYCON_RIGHT;
+		case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: return GAMEPAD_TYPE_JOYCON_PAIR;
 #endif
 	}
 #endif
@@ -509,7 +515,7 @@ bool Joystick::setVibration(float left, float right, float duration)
 	Uint32 length = SDL_HAPTIC_INFINITY;
 	if (duration >= 0.0f)
 	{
-		float maxduration = std::numeric_limits<Uint32>::max() / 1000.0f;
+		float maxduration = (float) (std::numeric_limits<Uint32>::max() / 1000.0);
 		length = Uint32(std::min(duration, maxduration) * 1000);
 	}
 

+ 36 - 0
src/modules/physics/box2d/World.cpp

@@ -171,6 +171,28 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture)
 	return true;
 }
 
+World::CollectCallback::CollectCallback(World *world, lua_State *L)
+	: world(world)
+	, L(L)
+{
+	lua_newtable(L);
+}
+
+World::CollectCallback::~CollectCallback()
+{
+}
+
+bool World::CollectCallback::ReportFixture(b2Fixture *f)
+{
+	Fixture *fixture = (Fixture *)world->findObject(f);
+	if (!fixture)
+		throw love::Exception("A fixture has escaped Memoizer!");
+	luax_pushtype(L, fixture);
+	lua_rawseti(L, -2, i);
+	i++;
+	return true;
+}
+
 World::RayCastCallback::RayCastCallback(World *world, lua_State *L, int idx)
 	: world(world)
 	, L(L)
@@ -556,6 +578,20 @@ int World::queryBoundingBox(lua_State *L)
 	return 0;
 }
 
+int World::getFixturesInArea(lua_State *L)
+{
+	float lx = (float)luaL_checknumber(L, 1);
+	float ly = (float)luaL_checknumber(L, 2);
+	float ux = (float)luaL_checknumber(L, 3);
+	float uy = (float)luaL_checknumber(L, 4);
+	b2AABB box;
+	box.lowerBound = Physics::scaleDown(b2Vec2(lx, ly));
+	box.upperBound = Physics::scaleDown(b2Vec2(ux, uy));
+	CollectCallback query(this, L);
+	world->QueryAABB(&query, box);
+	return 1;
+}
+
 int World::rayCast(lua_State *L)
 {
 	float x1 = (float)luaL_checknumber(L, 1);

+ 18 - 1
src/modules/physics/box2d/World.h

@@ -102,6 +102,18 @@ public:
 		int funcidx;
 	};
 
+	class CollectCallback : public b2QueryCallback
+	{
+	public:
+		CollectCallback(World *world, lua_State *L);
+		~CollectCallback();
+		virtual bool ReportFixture(b2Fixture *fixture);
+	private:
+		World *world;
+		lua_State *L;
+		int i = 1;
+	};
+
 	class RayCastCallback : public b2RayCastCallback
 	{
 	public:
@@ -270,10 +282,15 @@ public:
 	b2Body *getGroundBody() const;
 
 	/**
-	 * Gets all fixtures that overlap a given bounding box.
+	 * Calls a callback on all fixtures that overlap a given bounding box.
 	 **/
 	int queryBoundingBox(lua_State *L);
 
+	/**
+	 * Gets all fixtures that overlap a given bounding box.
+	 **/
+	int getFixturesInArea(lua_State *L);
+
 	/**
 	 * Raycasts the World for all Fixtures in the path of the ray.
 	 **/

+ 10 - 0
src/modules/physics/box2d/wrap_World.cpp

@@ -185,6 +185,15 @@ int w_World_queryBoundingBox(lua_State *L)
 	return t->queryBoundingBox(L);
 }
 
+int w_World_getFixturesInArea(lua_State *L)
+{
+	World *t = luax_checkworld(L, 1);
+	lua_remove(L, 1);
+	int ret = 0;
+	luax_catchexcept(L, [&](){ ret = t->getFixturesInArea(L); });
+	return ret;
+}
+
 int w_World_rayCast(lua_State *L)
 {
 	World *t = luax_checkworld(L, 1);
@@ -228,6 +237,7 @@ static const luaL_Reg w_World_functions[] =
 	{ "getJoints", w_World_getJoints },
 	{ "getContacts", w_World_getContacts },
 	{ "queryBoundingBox", w_World_queryBoundingBox },
+	{ "getFixturesInArea", w_World_getFixturesInArea },
 	{ "rayCast", w_World_rayCast },
 	{ "destroy", w_World_destroy },
 	{ "isDestroyed", w_World_isDestroyed },

+ 8 - 1
src/modules/sound/Decoder.cpp

@@ -39,7 +39,14 @@ Decoder::Decoder(Stream *stream, int bufferSize)
 	if (!stream->isReadable() || !stream->isSeekable())
 		throw love::Exception("Decoder input stream must be readable and seekable.");
 
-	buffer = new char[bufferSize];
+	try
+	{
+		buffer = new char[bufferSize];
+	}
+	catch (std::exception &)
+	{
+		throw love::Exception("Out of memory.");
+	}
 }
 
 Decoder::~Decoder()