소스 검색

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
{

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

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

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

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

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

if (!set)
return loaders;

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

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

virtual ~ImageData() {}

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

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

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



+ 65
- 16
src/image/image.cpp 파일 보기

@@ -20,18 +20,18 @@ using namespace std;
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()
{
/* 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__
REGISTER_IMAGE_LOADER(AndroidImageData)
#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) */
static bool init = RegisterAllLoaders();
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)
{
delete img;
return image_loader.Destroy(img);
}

/*


+ 2
- 0
src/lol/image/image.h 파일 보기

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

class Image
{
friend class ImageLoader;

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


불러오는 중...
취소
저장