浏览代码

image: try to reuse existing images when loading them, and don't unload

tilesets yet, but make sure the architecture will allow it.
legacy
Sam Hocevar sam 12 年前
父节点
当前提交
c54ca8bf40
共有 3 个文件被更改,包括 88 次插入29 次删除
  1. +21
    -13
      src/image/image-private.h
  2. +65
    -16
      src/image/image.cpp
  3. +2
    -0
      src/lol/image/image.h

+ 21
- 13
src/image/image-private.h 查看文件

@@ -19,17 +19,17 @@
namespace lol namespace lol
{ {


class ImageLoader
class ImageCodec
{ {
friend class Image;
friend class ImageLoader;
friend class ImageData; friend class ImageData;


public: public:
ImageData *(*fun)(char const *path); ImageData *(*fun)(char const *path);
ImageLoader *next;
ImageCodec *next;
int priority; int priority;


static void RegisterLoader(ImageLoader *loader)
static void RegisterLoader(ImageCodec *loader)
{ {
Helper(loader); Helper(loader);
} }
@@ -37,7 +37,7 @@ public:
private: private:
static ImageData *Load(char const *path) static ImageData *Load(char const *path)
{ {
ImageLoader *parser = Helper(nullptr);
ImageCodec *parser = Helper(nullptr);
ImageData *ret = nullptr; ImageData *ret = nullptr;


while (parser && !ret) while (parser && !ret)
@@ -49,14 +49,14 @@ private:
return ret; return ret;
} }


static ImageLoader *Helper(ImageLoader *set)
static ImageCodec *Helper(ImageCodec *set)
{ {
static ImageLoader *loaders = nullptr;
static ImageCodec *loaders = nullptr;


if (!set) if (!set)
return loaders; return loaders;


ImageLoader **parser = &loaders;
ImageCodec **parser = &loaders;
while (*parser && (*parser)->priority > set->priority) while (*parser && (*parser)->priority > set->priority)
parser = &(*parser)->next; parser = &(*parser)->next;
set->next = *parser; set->next = *parser;
@@ -69,8 +69,15 @@ private:
class ImageData class ImageData
{ {
friend class Image; friend class Image;
friend class ImageLoader;


public: public:
inline ImageData()
: m_size(0, 0),
m_format(PixelFormat::Unknown),
m_refcount(0)
{ }

virtual ~ImageData() {} virtual ~ImageData() {}


virtual bool Open(char const *) = 0; virtual bool Open(char const *) = 0;
@@ -81,6 +88,7 @@ public:
protected: protected:
ivec2 m_size; ivec2 m_size;
PixelFormat m_format; PixelFormat m_format;
int m_refcount;
}; };


#define REGISTER_IMAGE_LOADER(name) \ #define REGISTER_IMAGE_LOADER(name) \
@@ -88,12 +96,12 @@ protected:
Register##name(); Register##name();


#define DECLARE_IMAGE_LOADER(name, prio) \ #define DECLARE_IMAGE_LOADER(name, prio) \
template<typename T> class name##ImageLoader : public ImageLoader \
template<typename T> class name##ImageCodec : public ImageCodec \
{ \ { \
public: \ public: \
name##ImageLoader() \
name##ImageCodec() \
{ \ { \
static ImageLoader loader; \
static ImageCodec loader; \
loader.fun = Load; \ loader.fun = Load; \
loader.priority = prio; \ loader.priority = prio; \
RegisterLoader(&loader); \ RegisterLoader(&loader); \
@@ -110,10 +118,10 @@ protected:
} \ } \
}; \ }; \
class name; \ class name; \
name##ImageLoader<name> name##ImageLoaderInstance; \
name##ImageCodec<name> name##ImageCodecInstance; \
void Register##name() \ void Register##name() \
{ \ { \
(void)&name##ImageLoaderInstance; \
(void)&name##ImageCodecInstance; \
} \ } \
class name : public ImageData class name : public ImageData




+ 65
- 16
src/image/image.cpp 查看文件

@@ -20,18 +20,18 @@ using namespace std;
namespace lol namespace lol
{ {


/* HACK: We cannot make this an ImageCodec member function, because the
* REGISTER_IMAGE_LOADER macro forward-declares free functions from
* the "lol" namespace. An apparent bug in Visual Studio's compiler
* makes it think these functions are actually in the top-level
* namespace when the forward declaration is in a class member function.
* To avoid the problem, we make the forward declaration in a free
* function.
* The bug was reported to Microsoft and fixed by them, but the fix
* is not yet available.
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */
static bool RegisterAllLoaders() static bool RegisterAllLoaders()
{ {
/* HACK: We cannot make this an ImageLoader member function, because the
* REGISTER_IMAGE_LOADER macro forward-declares free functions from
* the "lol" namespace. An apparent bug in Visual Studio's compiler
* makes it think these functions are actually in the top-level
* namespace when the forward declaration is in a class member function.
* To avoid the problem, we make the forward declaration in a free
* function.
* The bug was reported to Microsoft and fixed by them, but the fix
* is not yet available.
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */
#if defined __ANDROID__ #if defined __ANDROID__
REGISTER_IMAGE_LOADER(AndroidImageData) REGISTER_IMAGE_LOADER(AndroidImageData)
#endif #endif
@@ -53,23 +53,72 @@ static bool RegisterAllLoaders()
} }


/* /*
* Static image loader
* Our static image loader
*/ */


Image *Image::Create(char const *path)
static class ImageLoader
{
public:
Image *Create(char const *path);
void Destroy(Image *img);

private:
Map<String, Image *> m_images;
}
image_loader;

Image *ImageLoader::Create(char const *path)
{ {
/* Initialise loaders (see above) */ /* Initialise loaders (see above) */
static bool init = RegisterAllLoaders(); static bool init = RegisterAllLoaders();
UNUSED(init); UNUSED(init);


Image *ret = new Image();
ret->m_data = ImageLoader::Load(path);
return ret;
/* Is our image already in the bank? If so, no need to create it. */
Image *img;

if (m_images.HasKey(path))
{
img = m_images[path];
}
else
{
img = new Image();
img->m_data = ImageCodec::Load(path);
m_images[path] = img;
}

++img->m_data->m_refcount;
return img;
}

void ImageLoader::Destroy(Image *img)
{
ASSERT(img->m_data->m_refcount > 0);
if (--img->m_data->m_refcount == 0)
{
/* FIXME: unload images etc. here */
/* XXX: we’re gonna hit a problem here because we didn’t keep
* the image path within the object, so unless we store it
* ourselves we’re good for a O(n) lookup… which we can’t do
* on Map objects anyway. */
/* TODO: 1. remove image from Map
2. delete img; */
}
}


/*
* Static image methods
*/

Image *Image::Create(char const *path)
{
return image_loader.Create(path);
} }


void Image::Destroy(Image *img) void Image::Destroy(Image *img)
{ {
delete img;
return image_loader.Destroy(img);
} }


/* /*


+ 2
- 0
src/lol/image/image.h 查看文件

@@ -23,6 +23,8 @@ namespace lol


class Image class Image
{ {
friend class ImageLoader;

public: public:
static Image *Create(char const *path); static Image *Create(char const *path);
static void Destroy(Image *img); static void Destroy(Image *img);


正在加载...
取消
保存