summaryrefslogtreecommitdiffstats
path: root/Tools/QtBiomeVisualiser/ChunkCache.cpp
blob: b2230def04578b11624799c01c5da922a596db49 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "Globals.h"
#include "ChunkCache.h"
#include <QMutexLocker>
#include <QThreadPool>
#include "ChunkSource.h"
#include "ChunkLoader.h"





ChunkCache::ChunkCache(QObject * parent) :
	super(parent)
{
	m_Cache.setMaxCost(1024 * 1024 * 1024);  // 1 GiB of memory for the cache
}





ChunkPtr ChunkCache::fetch(int a_ChunkX, int a_ChunkZ)
{
	// Retrieve from the cache:
	quint32 hash = getChunkHash(a_ChunkX, a_ChunkZ);
	ChunkPtr * res;
	{
		QMutexLocker lock(&m_Mtx);
		res = m_Cache[hash];
		// If succesful and chunk loaded, return the retrieved value:
		if ((res != nullptr) && (*res)->isValid())
		{
			return *res;
		}
	}

	// If the chunk is in cache but not valid, it means it has been already queued for rendering, do nothing now:
	if (res != nullptr)
	{
		return ChunkPtr(nullptr);
	}

	// There's no such item in the cache, create it now:
	res = new ChunkPtr(new Chunk);
	if (res == nullptr)
	{
		return ChunkPtr(nullptr);
	}
	{
		QMutexLocker lock(&m_Mtx);
		m_Cache.insert(hash, res, sizeof(Chunk));
	}

	// Queue the chunk for rendering:
	queueChunkRender(a_ChunkX, a_ChunkZ, *res);

	// Return failure, the chunk is not yet rendered:
	return ChunkPtr(nullptr);
}





void ChunkCache::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
{
	// Replace the chunk source:
	m_ChunkSource = a_ChunkSource;

	// Clear the cache:
	QMutexLocker lock(&m_Mtx);
	m_Cache.clear();
}





void ChunkCache::gotChunk(int a_ChunkX, int a_ChunkZ)
{
	emit chunkAvailable(a_ChunkX, a_ChunkZ);
}





quint32 ChunkCache::getChunkHash(int a_ChunkX, int a_ChunkZ)
{
	// Simply join the two coords into a single int
	// The coords will never be larger than 16-bits, so we can do this safely
	return (((static_cast<quint32>(a_ChunkX) & 0xffff) << 16) | (static_cast<quint32>(a_ChunkZ) & 0xffff));
}





void ChunkCache::queueChunkRender(int a_ChunkX, int a_ChunkZ, ChunkPtr & a_Chunk)
{
	// Create a new loader task:
	ChunkLoader * loader = new ChunkLoader(a_ChunkX, a_ChunkZ, a_Chunk, m_ChunkSource);
	connect(loader, SIGNAL(loaded(int, int)), this, SLOT(gotChunk(int, int)));

	QThreadPool::globalInstance()->start(loader);
}