--- /dev/null
+#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<TextureSpec, video::ITexture*, u8, u8>
+ request = m_get_texture_queue.pop();
+
+ dstream<<"got request with key.name="<<request.key.name<<std::endl;
+
+ GetResult<TextureSpec, video::ITexture*, u8, u8>
+ 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: "<<spec.name<<std::endl;
+ t = getTextureDirect(spec);
+ }
+ else
+ {
+ // We're gonna ask the result to be put into here
+ ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue;
+
+ // Throw a request in
+ m_get_texture_queue.add(spec, 0, 0, &result_queue);
+
+ dstream<<"Waiting for texture "<<spec.name<<std::endl;
+
+ // Wait result
+ GetResult<TextureSpec, video::ITexture*, u8, u8>
+ 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"<<std::endl;
+ }
+ return driver->getTexture(spec.path.c_str());
+}
+
+video::ITexture * CrackTextureMod::make(video::ITexture *original,
+ video::IVideoDriver* driver)
+{
+ //TODO
+ dstream<<__FUNCTION_NAME<<std::endl;
+ return NULL;
+}
+
+#if 0
+video::ITexture * createAlphaBlitTexture(const char *name, video::ITexture *base,
+ video::ITexture *other, v2u32 size, v2s32 pos_base, v2s32 pos_other)
+{
+ if(g_device == NULL)
+ return NULL;
+ video::IVideoDriver* driver = g_device->getVideoDriver();
+
+ core::dimension2d<u32> dim(size.X, size.Y);
+
+ video::IImage *baseimage = driver->createImage(
+ base,
+ core::position2d<s32>(pos_base.X, pos_base.Y),
+ dim);
+ assert(baseimage);
+
+ video::IImage *otherimage = driver->createImage(
+ other,
+ core::position2d<s32>(pos_other.X, pos_other.Y),
+ dim);
+ assert(sourceimage);
+
+ otherimage->copyToWithAlpha(baseimage, v2s32(0,0),
+ core::rect<s32>(v2s32(0,0), dim),
+ video::SColor(255,255,255,255),
+ core::rect<s32>(v2s32(0,0), dim));
+ otherimage->drop();
+
+ video::ITexture *newtexture = driver->addTexture(name, baseimage);
+
+ baseimage->drop();
+
+ return newtexture;
+}
+#endif
+
--- /dev/null
+/*
+Minetest-c55
+Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <jmutex.h>
+#include <jmutexautolock.h>
+#include <string>
+
+/*
+ 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<std::string, video::ITexture*>::Node *n;
+ n = m_textures.find(name);
+
+ if(n != NULL)
+ return n->getValue();
+
+ return NULL;
+ }
+
+private:
+ core::map<std::string, video::ITexture*> 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<TextureSpec, video::ITexture*, u8, u8> m_get_texture_queue;
+};
+
+#endif
+
+++ /dev/null
-/*
-Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
-
-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
-
--- /dev/null
+/*
+Minetest-c55
+Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <jmutex.h>
+
+#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
+