Texture TextureFactory::loadTexture(const std::string& fileName, ObjectsCache& cache, bool async, TextureLoaderDelegate* delegate) { if (fileName.length() == 0) return Texture(); CriticalSectionScope lock(_csTextureLoading); std::string file = application().environment().resolveScalableFileName(fileName, renderContext()->screenScaleFactor()); if (!fileExists(file)) { log::error("Unable to find texture file: %s", file.c_str()); return Texture(); } uint64_t cachedFileProperty = 0; Texture texture = cache.findAnyObject(file, &cachedFileProperty); if (texture.invalid()) { TextureDescription::Pointer desc = async ? et::loadTextureDescription(file, false) : et::loadTexture(file); if (desc.valid()) { bool calledFromAnotherThread = Threading::currentThread() != threading().renderingThread(); texture = Texture(new TextureData(renderContext(), desc, desc->origin(), async || calledFromAnotherThread)); cache.manage(texture, ObjectLoader::Pointer(this)); if (async) _loadingThread->addRequest(desc->origin(), texture, delegate); else if (calledFromAnotherThread) assert(false && "ERROR: Unable to load texture synchronously from non-rendering thread."); } } else { auto newProperty = cache.getFileProperty(file); if (cachedFileProperty != newProperty) reloadObject(texture, cache); if (async && (delegate != nullptr)) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidStartLoading, texture); i.invokeInMainRunLoop(); i.setTarget(delegate, &TextureLoaderDelegate::textureDidLoad, texture); i.invokeInMainRunLoop(); } } return texture; }
void TextureLoadingThread::addRequest(const std::string& fileName, Texture::Pointer texture, TextureLoaderDelegate* delegate) { if (delegate) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidStartLoading, texture); i.invokeInMainRunLoop(); } CriticalSectionScope lock(_requestsCriticalSection); _requests.push(etCreateObject<TextureLoadingRequest>(fileName, texture, delegate)); if (running()) resume(); else run(); }
uint64_t TextureLoadingThread::main() { while (running()) { TextureLoadingRequest* req = dequeRequest(); if (req) { req->textureDescription = loadTexture(req->fileName); Invocation1 invocation; invocation.setTarget(_delegate, &TextureLoadingThreadDelegate::textureLoadingThreadDidLoadTextureData, req); invocation.invokeInMainRunLoop(); } else { suspend(); } } return 0; }
Texture::Pointer TextureFactory::loadTexture(const std::string& fileName, ObjectsCache& cache, bool async, TextureLoaderDelegate* delegate) { if (fileName.length() == 0) return Texture::Pointer(); CriticalSectionScope lock(_csTextureLoading); auto file = resolveTextureName(fileName); if (!fileExists(file)) return Texture::Pointer(); uint64_t cachedFileProperty = 0; Texture::Pointer texture = cache.findAnyObject(file, &cachedFileProperty); if (texture.invalid()) { TextureDescription::Pointer desc = async ? et::loadTextureDescription(file, false) : et::loadTexture(file); int maxTextureSize = static_cast<int>(RenderingCapabilities::instance().maxTextureSize()); if ((desc->size.x > maxTextureSize) || (desc->size.y > maxTextureSize)) { log::warning("Attempt to load texture with dimensions (%d x %d) larger than max allowed (%d)", desc->size.x, desc->size.y, maxTextureSize); } if (desc.valid()) { bool calledFromAnotherThread = !threading::inMainThread(); texture = Texture::Pointer::create(renderContext(), desc, desc->origin(), async || calledFromAnotherThread); cache.manage(texture, _private->loader); if (async) { _loadingThread->addRequest(desc->origin(), texture, delegate); } else if (calledFromAnotherThread) { ET_FAIL("ERROR: Unable to load texture synchronously from non-rendering thread."); } } } else { auto newProperty = cache.getFileProperty(file); if (cachedFileProperty != newProperty) reloadObject(texture, cache); if (async) { textureDidStartLoading.invokeInMainRunLoop(texture); if (delegate != nullptr) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidStartLoading, texture); i.invokeInMainRunLoop(); } textureDidLoad.invokeInMainRunLoop(texture); if (delegate != nullptr) { Invocation1 i; i.setTarget(delegate, &TextureLoaderDelegate::textureDidLoad, texture); i.invokeInMainRunLoop(); } } } return texture; }