tile_cache.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // *****************************************************************************
29 
31 
32 // C++ standard libraries
33 #include <cmath>
34 #include <cstdlib>
35 #include <algorithm>
36 #include <iostream>
37 #include <exception>
38 
39 // QT libraries
40 #include <QApplication>
41 #include <QEvent>
42 
44 
45 namespace multires_image
46 {
47  TileCache::TileCache(TileSet* tileSet, QGLWidget* widget) :
48  m_tileSet(tileSet),
49  m_widget(widget),
50  m_currentLayer(0),
51  m_currentPosition(0, 0, 0),
52  m_exit(false),
53  m_memorySize(0),
54  m_cacheThread(this),
55  m_freeThread(this),
56  m_renderRequestsLock(QMutex::Recursive),
57  m_renderRequestSetLock(QMutex::Recursive),
58  m_precacheRequestsLock(QMutex::Recursive),
59  m_precacheRequestSetLock(QMutex::Recursive),
60  m_textureLoadedLock(QMutex::Recursive)
61  {
62  connect(this, SIGNAL(SignalLoadTexture(Tile*)),
63  SLOT(LoadTextureSlot(Tile*)), Qt::BlockingQueuedConnection);
64 
65  connect(this, SIGNAL(SignalDeleteTexture(Tile*)),
66  SLOT(DeleteTextureSlot(Tile*)), Qt::BlockingQueuedConnection);
67 
68  m_cacheThread.setPriority(QThread::NormalPriority);
69  m_cacheThread.start();
70 
71  m_freeThread.setPriority(QThread::LowPriority);
72  m_freeThread.start();
73 
74  for (int i = 0; i < m_tileSet->LayerCount(); i++)
75  {
76  m_precacheRequests.push_back(std::queue<Tile*>());
77  }
78  }
79 
81  {
82  m_exit = true;
83  m_cacheThread.wait();
84  m_freeThread.wait();
85  }
86 
88  {
89  tile->LoadTexture();
90  }
91 
93  {
94  tile->UnloadTexture();
95  }
96 
97  void TileCache::Load(Tile* tile)
98  {
99  m_renderRequestsLock.lock();
100  m_renderRequestSetLock.lock();
101 
102  try
103  {
104  if (m_renderRequestSet.count(tile->TileID()) == 0)
105  {
106  m_renderRequests.push(tile);
107  m_renderRequestSet[tile->TileID()] = tile;
108  }
109  }
110  catch(const std::exception& e)
111  {
112  std::cout << "An exception occurred queuing a tile to be cached: " << e.what() << std::endl;
113  }
114 
115  m_renderRequestSetLock.unlock();
116  m_renderRequestsLock.unlock();
117  }
118 
119  void TileCache::Precache(double x, double y)
120  {
121  tf::Point point(x, y, 0);
122  Precache(point);
123  }
124 
125  void TileCache::Precache(const tf::Point& position)
126  {
127  m_currentPosition = position;
128 
129  int sizes[] = {3, 2, 2, 1, 1, 1};
130 
132 
133  for (int i = 1; i <= 5; i++)
134  {
135  int layer = m_currentLayer + i;
136  if (layer < m_tileSet->LayerCount())
137  {
138  PrecacheLayer(layer, m_currentPosition, sizes[i]);
139  }
140 
141  layer = m_currentLayer - i;
142  if (layer >= 0)
143  {
144  PrecacheLayer(layer, m_currentPosition, sizes[i]);
145  }
146  }
147  }
148 
149  void TileCache::PrecacheLayer(int layerNum, const tf::Point& position, int size)
150  {
151  TileSetLayer* layer = m_tileSet->GetLayer(layerNum);
152 
153  int row, column;
154  layer->GetTileIndex(position, row, column);
155 
156  int startRow = std::max(0, row - size);
157  int endRow = std::min(layer->RowCount() - 1, row + size);
158  int startColumn = std::max(0, column - size);
159  int endColumn = std::min(layer->ColumnCount() - 1, column + size);
160 
161  for (int c = startColumn; c <= endColumn; c++)
162  {
163  for (int r = startRow; r <= endRow; r++)
164  {
165  Tile* tile = layer->GetTile(c, r);
166 
167  m_precacheRequestsLock.lock();
169 
170  try
171  {
172  if (m_precacheRequestSet.count(tile->TileID()) == 0)
173  {
174  m_precacheRequests[layerNum].push(tile);
175  m_precacheRequestSet[tile->TileID()] = tile;
176  }
177  }
178  catch (const std::exception& e)
179  {
180  std::cout << "An exception occurred queuing tiles for precaching: " << e.what() << std::endl;
181  }
182 
183  m_precacheRequestSetLock.unlock();
184  m_precacheRequestsLock.unlock();
185  }
186  }
187  }
188 
190  {
191  m_exit = true;
192  }
193 
195  {
196  Q_EMIT SignalLoadTexture(tile);
197 
198  m_memorySize += tile->MemorySize();
200 
201  m_textureLoadedLock.lock();
202 
203  try
204  {
205  m_textureLoaded[tile->TileID()] = tile;
206  }
207  catch (const std::exception& e)
208  {
209  std::cout << "An exception occurred loading texture: " << e.what() << std::endl;
210  }
211 
212  m_textureLoadedLock.unlock();
213 
214  if (tile->Layer() == m_currentLayer)
215  {
216  QApplication::postEvent(m_widget, new QEvent(QEvent::UpdateRequest));
217  }
218  }
219 
221  {
222  Q_EMIT SignalDeleteTexture(tile);
223 
224  m_memorySize -= tile->MemorySize();
226 
227  m_textureLoadedLock.lock();
228 
229  try
230  {
231  m_textureLoaded.erase(tile->TileID());
232  }
233  catch (const std::exception& e)
234  {
235  std::cout << "An exception occurred unloading texture: " << e.what() << std::endl;
236  }
237 
238  m_textureLoadedLock.unlock();
239  }
240 
242  {
243  while (!p->m_exit)
244  {
245  Tile* tile = NULL;
246  p->m_renderRequestsLock.lock();
247 
248  if (p->m_renderRequests.size() > 0)
249  {
250  tile = p->m_renderRequests.top();
251  p->m_renderRequests.pop();
252  }
253 
254  p->m_renderRequestsLock.unlock();
255 
256  if (tile != NULL)
257  {
258  if (!tile->Failed())
259  {
260  if (tile->Layer() == p->m_currentLayer)
261  {
262  int row, column;
263  p->m_tileSet->GetLayer(tile->Layer())->GetTileIndex(p->m_currentPosition, row, column);
264 
265  if (abs(tile->Row() - row) <= 3 || abs(tile->Column() - column) < 3)
266  {
267  if (!tile->TextureLoaded())
268  {
269  if (tile->LoadImageToMemory() == true)
270  {
271  p->LoadTexture(tile);
272  tile->UnloadImage();
273  }
274  else
275  {
276  printf("failed to load image\n");
277  }
278  }
279  }
280  }
281  else
282  {
283  p->m_precacheRequests[tile->Layer()].push(tile);
284  }
285 
286  p->m_renderRequestSetLock.lock();
287  p->m_renderRequestSet.erase(tile->TileID());
288  p->m_renderRequestSetLock.unlock();
289  }
290  else
291  {
292  }
293  }
294  else
295  {
296  p->m_precacheRequestsLock.lock();
297 
298  try
299  {
300  for (uint32_t i = 0; (i < p->m_precacheRequests.size()) && (tile == NULL); i++)
301  {
302  int32_t index = p->m_currentLayer + i;
303  if ((index < (int64_t)p->m_precacheRequests.size()) &&
304  (p->m_precacheRequests[index].size() > 0))
305  {
306  tile = p->m_precacheRequests[index].front();
307  p->m_precacheRequests[index].pop();
308  }
309  else if (i != 0)
310  {
311  index = p->m_currentLayer - i;
312  if (index >= 0 && p->m_precacheRequests[index].size() > 0)
313  {
314  tile = p->m_precacheRequests[index].front();
315  p->m_precacheRequests[index].pop();
316  }
317  }
318  }
319  }
320  catch (const std::exception& e)
321  {
322  std::cout << "An exception occurred precaching texture: " << e.what() << std::endl;
323  }
324 
325  p->m_precacheRequestsLock.unlock();
326 
327  if (tile != NULL && !tile->Failed() && !tile->TextureLoaded())
328  {
329  int row, column;
330  p->m_tileSet->GetLayer(tile->Layer())->GetTileIndex(p->m_currentPosition, row, column);
331  if (abs(tile->Row() - row) <= 3 || abs(tile->Column() - column) <= 3)
332  {
333  if (tile->LoadImageToMemory() == true)
334  {
335  p->LoadTexture(tile);
336 
337  tile->UnloadImage();
338  }
339  else
340  {
341  printf("failed to precache load image\n");
342  }
343  }
344 
345  p->m_precacheRequestSetLock.lock();
346  p->m_precacheRequestSet.erase(tile->TileID());
347  p->m_precacheRequestSetLock.unlock();
348  }
349  }
350 
351  if (tile == NULL)
352  {
353  usleep(10);
354  }
355  }
356  }
357 
359  {
360  while (!p->m_exit)
361  {
362  std::map<int64_t, Tile*>* tiles;
363  p->m_textureLoadedLock.lock();
364 
365  tiles = new std::map<int64_t, Tile*>(p->m_textureLoaded);
366 
367  p->m_textureLoadedLock.unlock();
368 
369  std::map<int64_t, Tile*>::iterator iter;
370 
371  for (iter = tiles->begin(); iter != tiles->end(); ++iter)
372  {
373  Tile* tile = iter->second;
374  int row, column;
375  p->m_tileSet->GetLayer(tile->Layer())->GetTileIndex(p->m_currentPosition, row, column);
376 
377  if (abs(tile->Row() - row) > 6 || abs(tile->Column() - column) > 6)
378  {
379  p->m_renderRequestSetLock.lock();
380  p->m_renderRequestSet.erase(tile->TileID());
381  p->m_renderRequestSetLock.unlock();
382 
383  p->m_precacheRequestSetLock.lock();
384  p->m_precacheRequestSet.erase(tile->TileID());
385  p->m_precacheRequestSetLock.unlock();
386 
387  p->UnloadTexture(tile);
388  }
389  }
390 
391  delete tiles;
392 
393  sleep(2);
394  }
395  }
396 }
#define NULL
void PrecacheLayer(int layer, const tf::Point &position, int size)
Definition: tile_cache.cpp:149
std::map< int64_t, Tile * > m_precacheRequestSet
Definition: tile_cache.h:89
int Column() const
Definition: tile.h:69
void SignalMemorySize(int64_t)
bool LoadImageToMemory(bool gl=true)
Definition: tile.cpp:80
int Layer() const
Definition: tile.h:66
TileCache(TileSet *tileSet, QGLWidget *widget)
Definition: tile_cache.cpp:47
int MemorySize() const
Definition: tile.h:67
void UnloadImage()
Definition: tile.cpp:129
void LoadTexture(Tile *tile)
Definition: tile_cache.cpp:194
std::stack< Tile * > m_renderRequests
Definition: tile_cache.h:86
std::map< int64_t, Tile * > m_renderRequestSet
Definition: tile_cache.h:88
bool Failed() const
Definition: tile.h:62
int Row() const
Definition: tile.h:68
std::map< int64_t, Tile * > m_textureLoaded
Definition: tile_cache.h:87
int64_t TileID() const
Definition: tile.h:65
void SignalLoadTexture(Tile *)
void DeleteTextureSlot(Tile *)
Definition: tile_cache.cpp:92
void UnloadTexture()
Definition: tile.cpp:176
void Precache(const tf::Point &position)
Definition: tile_cache.cpp:125
std::vector< std::queue< Tile * > > m_precacheRequests
Definition: tile_cache.h:85
TileSetLayer * GetLayer(int layer)
Definition: tile_set.h:61
Tile * GetTile(int column, int row)
bool LoadTexture()
Definition: tile.cpp:139
void UnloadTexture(Tile *tile)
Definition: tile_cache.cpp:220
void GetTileIndex(const tf::Point &position, int &row, int &column) const
void SignalDeleteTexture(Tile *)
void LoadTextureSlot(Tile *)
Definition: tile_cache.cpp:87
void Load(Tile *tile)
Definition: tile_cache.cpp:97
bool TextureLoaded() const
Definition: tile.h:63


multires_image
Author(s): Marc Alban
autogenerated on Fri Mar 19 2021 02:44:42