Merge branch '12.0-development' into metal

This commit is contained in:
Alex Szpakowski
2021-12-24 15:35:18 -04:00
61 changed files with 2101 additions and 2925 deletions
+154 -55
View File
@@ -333,24 +333,59 @@ void showRecordingPermissionMissingDialog()
env->DeleteLocalRef(activity);
}
/* A container for AssetManager Java object */
class AssetManagerObject
{
public:
AssetManagerObject()
{
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jobject am = getLocalAssetManager(env);
assetManager = env->NewGlobalRef(am);
env->DeleteLocalRef(am);
}
~AssetManagerObject()
{
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
env->DeleteGlobalRef(assetManager);
}
static jobject getLocalAssetManager(JNIEnv *env) {
jobject self = (jobject) SDL_AndroidGetActivity();
jclass activity = env->GetObjectClass(self);
jmethodID method = env->GetMethodID(activity, "getAssets", "()Landroid/content/res/AssetManager;");
jobject am = env->CallObjectMethod(self, method);
env->DeleteLocalRef(self);
env->DeleteLocalRef(activity);
return am;
}
explicit operator jobject()
{
return assetManager;
};
private:
jobject assetManager;
};
/*
* Helper functions to aid new fusing method
*/
// This returns *global* reference, no need to free it.
static jobject getJavaAssetManager()
{
static AssetManagerObject assetManager;
return (jobject) assetManager;
}
static AAssetManager *getAssetManager()
{
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jobject self = (jobject) SDL_AndroidGetActivity();
jclass activity = env->GetObjectClass(self);
jmethodID method = env->GetMethodID(activity, "getAssetManager", "()Landroid/content/res/AssetManager;");
jobject assetManager = env->CallObjectMethod(self, method);
AAssetManager *assetManagerObject = AAssetManager_fromJava(env, assetManager);
env->DeleteLocalRef(assetManager);
env->DeleteLocalRef(activity);
env->DeleteLocalRef(self);
return assetManagerObject;
return AAssetManager_fromJava(env, (jobject) getJavaAssetManager());
}
namespace aasset
@@ -368,35 +403,6 @@ struct AssetInfo
static std::unordered_map<std::string, PHYSFS_FileType> fileTree;
// Workaround AAsset can't detect whetever something is a directory or doesn't exist
static void buildFileLookup(
AAssetManager *assetManager,
std::unordered_map<std::string, PHYSFS_FileType> &out,
const std::string &path = ""
)
{
if (!path.empty())
{
AAsset *test = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_STREAMING);
if (test)
{
AAsset_close(test);
out[path] = PHYSFS_FILETYPE_REGULAR;
return;
}
out[path] = PHYSFS_FILETYPE_DIRECTORY;
}
AAssetDir *dir = AAssetManager_openDir(assetManager, path.c_str());
const char *file;
while ((file = AAssetDir_getNextFileName(dir)) != nullptr)
buildFileLookup(assetManager, out, file);
AAssetDir_close(dir);
}
PHYSFS_sint64 read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
{
AAsset *asset = ((AssetInfo *) io->opaque)->asset;
@@ -505,7 +511,31 @@ void *openArchive(PHYSFS_Io *io, const char *name, int forWrite, int *claimed)
AAssetManager *assetManager = getAssetManager();
if (io::fileTree.empty())
io::buildFileLookup(assetManager, io::fileTree);
{
// AAssetDir_getNextFileName intentionally excludes directories, so
// we have to use JNI that calls AssetManager.list() recursively.
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jobject activity = (jobject) SDL_AndroidGetActivity();
jclass clazz = env->GetObjectClass(activity);
jmethodID method = env->GetMethodID(clazz, "buildFileTree", "()[Ljava/lang/String;");
jobjectArray list = (jobjectArray) env->CallObjectMethod(activity, method);
for (jsize i = 0; i < env->GetArrayLength(list); i++)
{
jstring jstr = (jstring) env->GetObjectArrayElement(list, i);
const char *str = env->GetStringUTFChars(jstr, nullptr);
io::fileTree[str + 1] = str[0] == 'd' ? PHYSFS_FILETYPE_DIRECTORY : PHYSFS_FILETYPE_REGULAR;
env->ReleaseStringUTFChars(jstr, str);
env->DeleteLocalRef(jstr);
}
env->DeleteLocalRef(list);
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(activity);
}
return assetManager;
}
@@ -518,33 +548,60 @@ PHYSFS_EnumerateCallbackResult enumerate(
void *callbackdata
)
{
using FileTreeIterator = std::unordered_map<std::string, PHYSFS_FileType>::iterator;
LOVE_UNUSED(opaque);
const char *path = dirname;
if (path == nullptr || (path[0] == '/' && path[1] == 0))
path = "";
AAssetManager *assetManager = (AAssetManager *) opaque;
AAssetDir *dir = AAssetManager_openDir(assetManager, path);
if (dir == nullptr)
if (path[0] != 0)
{
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
return PHYSFS_ENUM_ERROR;
FileTreeIterator result = io::fileTree.find(path);
if (result == io::fileTree.end() || result->second != PHYSFS_FILETYPE_DIRECTORY)
{
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
return PHYSFS_ENUM_ERROR;
}
}
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
jobject assetManager = getJavaAssetManager();
jclass clazz = env->GetObjectClass(assetManager);
jmethodID method = env->GetMethodID(clazz, "list", "(Ljava/lang/String;)[Ljava/lang/String;");
jstring jstringDir = env->NewStringUTF(path);
jobjectArray dir = (jobjectArray) env->CallObjectMethod(assetManager, method, jstringDir);
PHYSFS_EnumerateCallbackResult ret = PHYSFS_ENUM_OK;
while (ret == PHYSFS_ENUM_OK)
if (env->ExceptionCheck())
{
const char *name = AAssetDir_getNextFileName(dir);
// IOException occured
ret = PHYSFS_ENUM_ERROR;
env->ExceptionClear();
}
else
{
jsize i = 0;
jsize len = env->GetArrayLength(dir);
// No more files?
if (name == nullptr)
break;
while (ret == PHYSFS_ENUM_OK && i < len) {
jstring jstr = (jstring) env->GetObjectArrayElement(dir, i++);
const char *name = env->GetStringUTFChars(jstr, nullptr);
ret = cb(callbackdata, origdir, name);
ret = cb(callbackdata, origdir, name);
env->ReleaseStringUTFChars(jstr, name);
env->DeleteLocalRef(jstr);
}
env->DeleteLocalRef(dir);
}
AAssetDir_close(dir);
env->DeleteLocalRef(jstringDir);
env->DeleteLocalRef(clazz);
return ret;
}
@@ -724,6 +781,48 @@ bool checkFusedGame(void **physfsIO_Out)
return false;
}
const char *getCRequirePath()
{
static bool initialized = false;
static const char *path = nullptr;
if (!initialized)
{
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jobject activity = (jobject) SDL_AndroidGetActivity();
jclass clazz(env->GetObjectClass(activity));
jmethodID method_id = env->GetMethodID(clazz, "getCRequirePath", "()Ljava/lang/String;");
path = "";
initialized = true;
if (method_id)
{
jstring cpath = (jstring) env->CallObjectMethod(activity, method_id);
const char *utf = env->GetStringUTFChars(cpath, nullptr);
if (utf)
{
path = SDL_strdup(utf);
env->ReleaseStringUTFChars(cpath, utf);
}
env->DeleteLocalRef(cpath);
}
else
{
// NoSuchMethodException is thrown in case methodID is null
env->ExceptionClear();
return "";
}
env->DeleteLocalRef(activity);
env->DeleteLocalRef(clazz);
}
return path;
}
} // android
} // love
+2
View File
@@ -101,6 +101,8 @@ void deinitializeVirtualArchive();
*/
bool checkFusedGame(void **physfsIO_Out);
const char *getCRequirePath();
} // android
} // love
+5 -1
View File
@@ -1156,7 +1156,9 @@ void luax_runwrapper(lua_State *L, const char *filedata, size_t datalen, const c
// functions struct pointer as arguments.
if (lua_istable(L, -1))
{
luaL_loadbuffer(L, filedata, datalen, filename);
std::string chunkname = std::string("=[love \"") + std::string(filename) + std::string("\"]");
luaL_loadbuffer(L, filedata, datalen, chunkname.c_str());
lua_pushvalue(L, -2);
if (ffifuncs != nullptr)
luax_pushpointerasstring(L, ffifuncs);
@@ -1179,8 +1181,10 @@ int luax_resume(lua_State *L, int nargs, int* nres)
#if LUA_VERSION_NUM >= 504
return lua_resume(L, nullptr, nargs, nres);
#elif LUA_VERSION_NUM >= 502
LOVE_UNUSED(nres);
return lua_resume(L, nullptr, nargs);
#else
LOVE_UNUSED(nres);
return lua_resume(L, nargs);
#endif
}