From e1d1ecfd81eab981b34c17ef3b9ae7d98f98121c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20=E2=80=98Touky=E2=80=99=20Huet?= Date: Mon, 16 Mar 2015 04:10:04 +0000 Subject: [PATCH] Added AsyncImageLoader to load images on threads Inverted image/all.h and thread/all.h to ensure build Added Image::DummyFill that uses DummyImageCodec to fill empty image Added Log:: Error/Info in image Load/Save --- src/image/codec/android-image.cpp | 1 + src/image/codec/dummy-image.cpp | 7 +- src/image/codec/gdiplus-image.cpp | 1 + src/image/codec/ios-image.cpp | 1 + src/image/codec/oric-image.cpp | 1 + src/image/codec/sdl-image.cpp | 1 + src/image/codec/zed-image.cpp | 3 +- src/image/codec/zed-palette-image.cpp | 3 +- src/image/image-private.h | 1 + src/image/image.cpp | 60 +++++++++++++--- src/lol/image/image.h | 3 + src/lol/public.h | 2 +- src/lol/sys/thread.h | 7 +- src/lol/sys/threadtypes.h | 100 ++++++++++++++++++++++++-- src/sys/thread.cpp | 4 +- 15 files changed, 166 insertions(+), 29 deletions(-) diff --git a/src/image/codec/android-image.cpp b/src/image/codec/android-image.cpp index 9b1c2ea0..8025647d 100644 --- a/src/image/codec/android-image.cpp +++ b/src/image/codec/android-image.cpp @@ -33,6 +33,7 @@ extern ANativeActivity *g_activity; class AndroidImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); virtual bool Close(); diff --git a/src/image/codec/dummy-image.cpp b/src/image/codec/dummy-image.cpp index 16ac8049..6f4c21e9 100644 --- a/src/image/codec/dummy-image.cpp +++ b/src/image/codec/dummy-image.cpp @@ -22,10 +22,12 @@ namespace lol class DummyImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); }; +//Priority 0 because it's supposed to be the last one DECLARE_IMAGE_CODEC(DummyImageCodec, 0) /* @@ -49,14 +51,15 @@ bool DummyImageCodec::Load(Image *image, char const *path) } image->Unlock(pixels); - return true; + //return false, because we're not supposed to be here. + return false; } bool DummyImageCodec::Save(Image *image, char const *path) { UNUSED(path); - return true; + return false; } } /* namespace lol */ diff --git a/src/image/codec/gdiplus-image.cpp b/src/image/codec/gdiplus-image.cpp index 083392cb..d79e4571 100644 --- a/src/image/codec/gdiplus-image.cpp +++ b/src/image/codec/gdiplus-image.cpp @@ -36,6 +36,7 @@ namespace lol class GdiPlusImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); }; diff --git a/src/image/codec/ios-image.cpp b/src/image/codec/ios-image.cpp index c9e158a8..7d38a161 100644 --- a/src/image/codec/ios-image.cpp +++ b/src/image/codec/ios-image.cpp @@ -26,6 +26,7 @@ namespace lol class IosImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); }; diff --git a/src/image/codec/oric-image.cpp b/src/image/codec/oric-image.cpp index 3eeab8b4..fc29fd36 100644 --- a/src/image/codec/oric-image.cpp +++ b/src/image/codec/oric-image.cpp @@ -30,6 +30,7 @@ namespace lol class OricImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); diff --git a/src/image/codec/sdl-image.cpp b/src/image/codec/sdl-image.cpp index a20ca0a7..673ab32a 100644 --- a/src/image/codec/sdl-image.cpp +++ b/src/image/codec/sdl-image.cpp @@ -35,6 +35,7 @@ namespace lol class SdlImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); diff --git a/src/image/codec/zed-image.cpp b/src/image/codec/zed-image.cpp index 2e48d889..b9fc5ce6 100644 --- a/src/image/codec/zed-image.cpp +++ b/src/image/codec/zed-image.cpp @@ -23,6 +23,7 @@ namespace lol class ZedImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); @@ -39,7 +40,7 @@ private: array m_tiles; }; -DECLARE_IMAGE_CODEC(ZedImageCodec, 0) +DECLARE_IMAGE_CODEC(ZedImageCodec, 10) /* * Public Image class diff --git a/src/image/codec/zed-palette-image.cpp b/src/image/codec/zed-palette-image.cpp index 882a52b7..f459d9c8 100644 --- a/src/image/codec/zed-palette-image.cpp +++ b/src/image/codec/zed-palette-image.cpp @@ -22,11 +22,12 @@ namespace lol class ZedPaletteImageCodec : public ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path); virtual bool Save(Image *image, char const *path); }; -DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 0) +DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10) /* * Public Image class diff --git a/src/image/image-private.h b/src/image/image-private.h index 52c9178f..8f130e2d 100644 --- a/src/image/image-private.h +++ b/src/image/image-private.h @@ -69,6 +69,7 @@ public: class ImageCodec { public: + virtual char const *GetName() { return ""; } virtual bool Load(Image *image, char const *path) = 0; virtual bool Save(Image *image, char const *path) = 0; diff --git a/src/image/image.cpp b/src/image/image.cpp index b0d5b0fd..ae59fce7 100644 --- a/src/image/image.cpp +++ b/src/image/image.cpp @@ -98,17 +98,7 @@ Image::Image(ivec2 size) Image::Image (Image const &other) : m_data(new ImageData()) { - ivec2 size = other.GetSize(); - PixelFormat fmt = other.GetFormat(); - - SetSize(size); - if (fmt != PixelFormat::Unknown) - { - SetFormat(fmt); - memcpy(m_data->m_pixels[(int)fmt]->data(), - other.m_data->m_pixels[(int)fmt]->data(), - size.x * size.y * BytesPerPixel(fmt)); - } + Copy(other); } Image & Image::operator =(Image other) @@ -127,19 +117,67 @@ Image::~Image() delete m_data; } +void Image::DummyFill() +{ + //TODO: This is not very beautiful + for (auto codec : g_image_loader.m_codecs) + { + if (String(codec->GetName()).Contains("Dummy")) + { + codec->Load(this, nullptr); + return; + } + } +} + +void Image::Copy(Image const &other) +{ + ivec2 size = other.GetSize(); + PixelFormat fmt = other.GetFormat(); + + SetSize(size); + if (fmt != PixelFormat::Unknown) + { + SetFormat(fmt); + memcpy(m_data->m_pixels[(int)fmt]->data(), + other.m_data->m_pixels[(int)fmt]->data(), + size.x * size.y * BytesPerPixel(fmt)); + } +} + bool Image::Load(char const *path) { + ImageCodec* last_codec = nullptr; for (auto codec : g_image_loader.m_codecs) + { + last_codec = codec; if (codec->Load(this, path)) + { + Log::Info("Image::Load: Codec %s succesfully loaded %s.\n", codec->GetName(), path); return true; + } + } + + //Log error, because we shouldn't be here + Log::Error("Image::Load: Last codec %s, Error loading image %s.\n", last_codec->GetName(), path); return false; } bool Image::Save(char const *path) { + ImageCodec* last_codec = nullptr; for (auto codec : g_image_loader.m_codecs) + { + last_codec = codec; if (codec->Save(this, path)) + { + Log::Info("Image::Save: Codec %s succesfully saved %s.\n", codec->GetName(), path); return true; + } + } + + //Log error, because we shouldn't be here + Log::Error("Image::Save: Last codec %s, Error saving image %s.\n", last_codec->GetName(), path); return false; } diff --git a/src/lol/image/image.h b/src/lol/image/image.h index cc5ed872..11d8223a 100644 --- a/src/lol/image/image.h +++ b/src/lol/image/image.h @@ -56,6 +56,7 @@ enum class EdiffAlgorithm : uint8_t Lite, }; +//Image ----------------------------------------------------------------------- class Image { public: @@ -70,6 +71,8 @@ public: Image & operator =(Image other); ~Image(); + void DummyFill(); + void Copy(Image const &other); bool Load(char const *path); bool Save(char const *path); diff --git a/src/lol/public.h b/src/lol/public.h index bd56b9bd..36db90c2 100644 --- a/src/lol/public.h +++ b/src/lol/public.h @@ -18,8 +18,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/lol/sys/thread.h b/src/lol/sys/thread.h index e081ef62..e32d34b4 100644 --- a/src/lol/sys/thread.h +++ b/src/lol/sys/thread.h @@ -113,21 +113,16 @@ protected: class BaseThreadManager : public Entity { public: + char const *GetName() { return ""; } BaseThreadManager(int thread_count); BaseThreadManager(int thread_count, int thread_min); ~BaseThreadManager(); - char const *GetName() { return ""; } - //Initialize, Ticker::Ref and start the thread bool Start(); //Stop the threads bool Stop(); - //Children class intergace - virtual bool AddJob(ThreadJob* job) { ASSERT(false); return false; } - virtual bool GetWorkResult(array& results) { ASSERT(false); return false; } - protected: //Thread addition void AddThreads(int nb); diff --git a/src/lol/sys/threadtypes.h b/src/lol/sys/threadtypes.h index 02070c40..e3469c02 100644 --- a/src/lol/sys/threadtypes.h +++ b/src/lol/sys/threadtypes.h @@ -25,6 +25,7 @@ namespace lol class DefaultThreadManager : public BaseThreadManager { public: + char const *GetName() { return ""; } DefaultThreadManager(int thread_count) : BaseThreadManager(thread_count, thread_count) { } @@ -32,8 +33,6 @@ public: : BaseThreadManager(thread_count, thread_min) { } - char const *GetName() { return ""; } - //Work stuff bool AddJob(ThreadJob* job); bool GetWorkResult(array& results); @@ -70,7 +69,8 @@ protected: bool m_updated = false; }; -//Test the files registered and warns when they update ------------------------ +//FileUpdateTester ------------------------------------------------------------ +//Test the files registered and warns when they update class FileUpdateTester : public BaseThreadManager { typedef BaseThreadManager super; @@ -80,9 +80,9 @@ public: bool m_updated = false; }; public: + char const *GetName() { return ""; } FileUpdateTester() : BaseThreadManager(1) { } ~FileUpdateTester() { } - char const *GetName() { return ""; } //------------------------------------------------------------------------- FileUpdateTester::Status* RegisterFile(String const& path); @@ -94,5 +94,97 @@ private: map m_files; }; +//AsyncImageJob --------------------------------------------------------------- +class AsyncImageJob : public ThreadJob +{ +public: + AsyncImageJob() + : ThreadJob(ThreadJobType::NONE) + { + m_path = String(); + } + AsyncImageJob(String path) + : ThreadJob(ThreadJobType::WORK_TODO) + { + m_path = path; + } + String const& GetPath() { return m_path; } + Image const& GetImage() { return m_image; } + +protected: + virtual bool DoWork() + { + return m_image.Load(m_path.C()); + } + + String m_path; + Image m_image; +}; + +//AsyncImageLoader ------------------------------------------------------------ +//Load images asynchronously, automatically updating the dummy image +class AsyncImageLoader : public BaseThreadManager +{ +public: + char const *GetName() { return ""; } + AsyncImageLoader(int thread_count) + : BaseThreadManager(thread_count, 0) + { + m_dummy_image.DummyFill(); + } + ~AsyncImageLoader() + { } + + //Returns a dummy image, and start a job to load the image on a thread + Image* Load(const lol::String& path) + { + //Create a job + AsyncImageJob* job = new AsyncImageJob(path); + //Create a dummy image + Image* image = new Image(m_dummy_image); + //Link the two + m_images[path] = image; + //Add job + AddWork(job); + //return Dummy image + return image; + } + bool CheckStatus(Image* image) + { + if (m_loaded_images.find(image) != INDEX_NONE) + { + m_loaded_images.remove_item(image); + return true; + } + return false; + } + +protected: + virtual void TreatResult(ThreadJob* result) + { + AsyncImageJob* job = dynamic_cast(result); + ASSERT(job); + //Copy image if work is OK + if (job->GetJobType() != ThreadJobType::WORK_FAILED) + { + Image* src = m_images[job->GetPath()]; + m_images.remove(job->GetPath()); + src->Copy(job->GetImage()); + m_loaded_images.PushUnique(src); + } + else + { + Log::Error("AsyncImageJob FAILED. See load image error above.\n"); + } + //Delete all that + delete(result); + } + +private: + Image m_dummy_image; + map m_images; + array m_loaded_images; +}; + } /* namespace lol */ diff --git a/src/sys/thread.cpp b/src/sys/thread.cpp index a706b3a8..df637606 100644 --- a/src/sys/thread.cpp +++ b/src/sys/thread.cpp @@ -166,10 +166,8 @@ void BaseThreadManager::TickGame(float seconds) { ThreadJob* job = result[i]; if (job->GetJobType() == ThreadJobType::WORK_DONE) - { job->SetJobType(ThreadJobType::WORK_FETCHED); - TreatResult(job); - } + TreatResult(job); } }