diff --git a/src/irrlichtwrapper.cpp b/src/irrlichtwrapper.cpp new file mode 100644 index 0000000..69b08a6 --- /dev/null +++ b/src/irrlichtwrapper.cpp @@ -0,0 +1,136 @@ +#include "irrlichtwrapper.h" + +IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device) +{ + m_main_thread = get_current_thread_id(); + m_device_mutex.Init(); + m_device = device; +} + +void IrrlichtWrapper::Run() +{ + /* + Fetch textures + */ + if(m_get_texture_queue.size() > 0) + { + GetRequest + request = m_get_texture_queue.pop(); + + dstream<<"got request with key.name="< + result; + result.key = request.key; + result.callers = request.callers; + result.item = getTextureDirect(request.key); + + request.dest->push_back(result); + } +} + +video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) +{ + video::ITexture *t = m_texturecache.get(spec.name); + if(t != NULL) + return t; + + if(get_current_thread_id() == m_main_thread) + { + dstream<<"Loading texture directly: "< result_queue; + + // Throw a request in + m_get_texture_queue.add(spec, 0, 0, &result_queue); + + dstream<<"Waiting for texture "< + result = result_queue.pop_front(true); + + // Check that at least something worked OK + assert(result.key.name == spec.name); + + t = result.item; + } + + // Add to cache and return + m_texturecache.set(spec.name, t); + return t; +} + +video::ITexture* IrrlichtWrapper::getTexture(const std::string &path) +{ + /*TextureSpec spec; + spec.name = path; + spec.path = path; + return getTexture(spec);*/ + return getTexture(TextureSpec(path, path, NULL)); +} + +/* + Non-thread-safe functions +*/ + +video::ITexture* IrrlichtWrapper::getTextureDirect(TextureSpec spec) +{ + video::IVideoDriver* driver = m_device->getVideoDriver(); + //TODO + if(spec.mod != NULL) + { + dstream<<"IrrlichtWrapper::getTextureDirect: Modified textures" + " not supported"<getTexture(spec.path.c_str()); +} + +video::ITexture * CrackTextureMod::make(video::ITexture *original, + video::IVideoDriver* driver) +{ + //TODO + dstream<<__FUNCTION_NAME<getVideoDriver(); + + core::dimension2d dim(size.X, size.Y); + + video::IImage *baseimage = driver->createImage( + base, + core::position2d(pos_base.X, pos_base.Y), + dim); + assert(baseimage); + + video::IImage *otherimage = driver->createImage( + other, + core::position2d(pos_other.X, pos_other.Y), + dim); + assert(sourceimage); + + otherimage->copyToWithAlpha(baseimage, v2s32(0,0), + core::rect(v2s32(0,0), dim), + video::SColor(255,255,255,255), + core::rect(v2s32(0,0), dim)); + otherimage->drop(); + + video::ITexture *newtexture = driver->addTexture(name, baseimage); + + baseimage->drop(); + + return newtexture; +} +#endif + diff --git a/src/irrlichtwrapper.h b/src/irrlichtwrapper.h new file mode 100644 index 0000000..a78edfe --- /dev/null +++ b/src/irrlichtwrapper.h @@ -0,0 +1,182 @@ +/* +Minetest-c55 +Copyright (C) 2010 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef IRRLICHTWRAPPER_HEADER +#define IRRLICHTWRAPPER_HEADER + +#include "threads.h" +#include "common_irrlicht.h" +#include "debug.h" +#include "utility.h" + +#include +#include +#include + +/* + A thread-safe texture pointer cache. + + This is used so that irrlicht doesn't get called from many + threads, because texture pointers have to be handled in + background threads. +*/ + +class TextureCache +{ +public: + TextureCache() + { + m_mutex.Init(); + assert(m_mutex.IsInitialized()); + } + + void set(std::string name, video::ITexture *texture) + { + JMutexAutoLock lock(m_mutex); + + m_textures[name] = texture; + } + + video::ITexture* get(std::string name) + { + JMutexAutoLock lock(m_mutex); + + core::map::Node *n; + n = m_textures.find(name); + + if(n != NULL) + return n->getValue(); + + return NULL; + } + +private: + core::map m_textures; + JMutex m_mutex; +}; + +struct TextureMod +{ + /* + Returns a new texture which can be based on the original. + Shall not modify or delete the original texture. + */ + virtual video::ITexture * make(video::ITexture *original, + video::IVideoDriver* driver) = 0; +}; + +struct CrackTextureMod: public TextureMod +{ + CrackTextureMod(u16 a_progression) + { + progression = a_progression; + } + + virtual video::ITexture * make(video::ITexture *original, + video::IVideoDriver* driver); + + u16 progression; +}; + +/* + A class for specifying a requested texture +*/ +struct TextureSpec +{ + TextureSpec() + { + mod = NULL; + } + TextureSpec(const std::string &a_name, const std::string &a_path, + TextureMod *a_mod) + { + name = a_name; + path = a_path; + mod = a_mod;; + } + ~TextureSpec() + { + } + bool operator==(const TextureSpec &other) + { + return name == other.name; + } + // An unique name for the texture. Usually the same as the path. + // Note that names and paths reside the same namespace. + std::string name; + // This is the path of the base texture + std::string path; + // Modification to do to the base texture + // NOTE: This is deleted by the one who processes the request + TextureMod *mod; +}; + +/* + A thread-safe wrapper for irrlicht, to be accessed from + background worker threads. + + Queues tasks to be done in the main thread. +*/ + +class IrrlichtWrapper +{ +public: + /* + These are called from the main thread + */ + IrrlichtWrapper(IrrlichtDevice *device); + + // Run queued tasks + void Run(); + + /* + These are called from other threads + */ + + // Not exactly thread-safe but this needs to be fast + u32 getTime() + { + return m_device->getTimer()->getTime(); + } + + video::ITexture* getTexture(TextureSpec spec); + video::ITexture* getTexture(const std::string &path); + +private: + /* + Non-thread-safe variants of stuff, for internal use + */ + video::ITexture* getTextureDirect(TextureSpec spec); + + /* + Members + */ + + threadid_t m_main_thread; + + JMutex m_device_mutex; + IrrlichtDevice *m_device; + + TextureCache m_texturecache; + + RequestQueue m_get_texture_queue; +}; + +#endif + diff --git a/src/loadstatus.h b/src/loadstatus.h deleted file mode 100644 index 06d515a..0000000 --- a/src/loadstatus.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef LOADSTATUS_HEADER -#define LOADSTATUS_HEADER - -class LoadStatus -{ - bool ready; - JMutex ready_mutex; - - u32 done; - JMutex done_mutex; - - u32 todo; - JMutex todo_mutex; - - wchar_t *text; - JMutex text_mutex; - -public: - - LoadStatus(bool a_ready=false, u32 a_done=0, u32 a_todo=0) - { - ready = a_ready; - done = a_done; - todo = a_todo; - text = NULL; - ready_mutex.Init(); - done_mutex.Init(); - todo_mutex.Init(); - text_mutex.Init(); - } - - void setReady(bool a_ready) - { - ready_mutex.Lock(); - ready = a_ready; - ready_mutex.Unlock(); - } - - bool getReady(void) - { - ready_mutex.Lock(); - bool a_ready = ready; - ready_mutex.Unlock(); - return a_ready; - } - - void setDone(u32 a_done) - { - done_mutex.Lock(); - done = a_done; - done_mutex.Unlock(); - } - - u32 getDone(void) - { - done_mutex.Lock(); - u32 a_done = done; - done_mutex.Unlock(); - return a_done; - } - - void setTodo(u32 a_todo) - { - todo_mutex.Lock(); - todo = a_todo; - todo_mutex.Unlock(); - } - - u32 getTodo(void) - { - todo_mutex.Lock(); - u32 a_todo = todo; - todo_mutex.Unlock(); - return a_todo; - } - - /* - Copies the text if not NULL, - If NULL; sets text to NULL. - */ - void setText(const wchar_t *a_text) - { - text_mutex.Lock(); - if(text != NULL) - free(text); - if(a_text == NULL){ - text = NULL; - text_mutex.Unlock(); - return; - } - u32 len = wcslen(a_text); - text = (wchar_t*)malloc(sizeof(wchar_t) * (len+1)); - if(text == NULL) throw; - swprintf(text, len+1, L"%ls", a_text); - text_mutex.Unlock(); - } - - /* - Return value must be free'd - Return value can be NULL - */ - wchar_t * getText() - { - text_mutex.Lock(); - if(text == NULL){ - text_mutex.Unlock(); - return NULL; - } - u32 len = wcslen(text); - wchar_t *b_text = (wchar_t*)malloc(sizeof(wchar_t) * (len+1)); - if(b_text == NULL) throw; - swprintf(b_text, len+1, L"%ls", text); - text_mutex.Unlock(); - return b_text; - } - - /* - Return value must be free'd - */ - wchar_t * getNiceText() - { - const wchar_t *defaulttext = L"Loading"; - wchar_t *t = getText(); - u32 maxlen = 20; // " (%i/%i)" - if(t != NULL) - maxlen += wcslen(t); - else - maxlen += wcslen(defaulttext); - wchar_t *b_text = (wchar_t*)malloc(sizeof(wchar_t) * (maxlen+1)); - if(b_text == NULL) throw; - if(t != NULL) - swprintf(b_text, maxlen+1, L"%ls (%i/%i)", - t, getDone(), getTodo()); - else - swprintf(b_text, maxlen+1, L"%ls (%i/%i)", - defaulttext, getDone(), getTodo()); - if(t != NULL) - free(t); - return b_text; - } -}; - -#endif - diff --git a/src/threads.h b/src/threads.h new file mode 100644 index 0000000..1ea7d0a --- /dev/null +++ b/src/threads.h @@ -0,0 +1,45 @@ +/* +Minetest-c55 +Copyright (C) 2010 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef THREADS_HEADER +#define THREADS_HEADER + +#include + +#if (defined(WIN32) || defined(_WIN32_WCE)) +typedef DWORD threadid_t; +#define __NORETURN __declspec(noreturn) +#define __FUNCTION_NAME __FUNCTION__ +#else +typedef pthread_t threadid_t; +#define __NORETURN __attribute__ ((__noreturn__)) +#define __FUNCTION_NAME __PRETTY_FUNCTION__ +#endif + +inline threadid_t get_current_thread_id() +{ +#if (defined(WIN32) || defined(_WIN32_WCE)) + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +#endif +