28#include <wx/tokenzr.h>
29#include <wx/filename.h>
34#include "mipmap/mipmap.h"
54#ifndef GL_ETC1_RGB8_OES
55#define GL_ETC1_RGB8_OES 0x8D64
60typedef void (*PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers);
61typedef void (*PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
62typedef void (*PFNGLDELETEBUFFERSPROC)(GLsizei n,
const GLuint *buffers);
63typedef void (*PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname,
65typedef void (*PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n,
66 const GLuint *renderbuffers);
67typedef void (*PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n,
68 const GLuint *framebuffers);
69typedef void (*PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level,
70 GLint xoffset, GLsizei width,
74typedef void (*PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level,
76typedef GLenum (*PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
77typedef void (*PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target,
79typedef void (*PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size,
80 const GLvoid *data, GLenum usage);
81typedef void (*PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint *framebuffers);
82typedef void (*PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint *renderbuffers);
83typedef void (*PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target,
86 GLuint texture, GLint level);
87typedef void (*PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level,
88 GLenum internalformat,
89 GLsizei width, GLsizei height,
90 GLint border, GLsizei imageSize,
92typedef void (*PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target,
94 GLenum renderbuffertarget,
96typedef void (*PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target,
97 GLenum internalformat,
98 GLsizei width, GLsizei height);
99typedef void (*PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
102extern ColorScheme global_color_scheme;
108extern wxString CompressedCachePath(wxString path);
111CatalogEntry::CatalogEntry() {}
113CatalogEntry::~CatalogEntry() {}
115CatalogEntry::CatalogEntry(
int level,
int x0,
int y0, ColorScheme colorscheme) {
119 k.tcolorscheme = colorscheme;
122int CatalogEntry::GetSerialSize() {
return CATALOG_ENTRY_SERIAL_SIZE; }
124void CatalogEntry::Serialize(
unsigned char *t) {
125 uint32_t *p = (uint32_t *)t;
130 *p++ = k.tcolorscheme;
131 *p++ = v.texture_offset;
132 *p++ = v.compressed_size;
135void CatalogEntry::DeSerialize(
unsigned char *t) {
136 uint32_t *p = (uint32_t *)t;
141 k.tcolorscheme = (ColorScheme)*p++;
142 v.texture_offset = *p++;
143 v.compressed_size = *p++;
147enum TextureDataType { COMPRESSED_BUFFER_OK, MAP_BUFFER_OK };
149glTexFactory::glTexFactory(
ChartBase *chart,
int raster_format) {
151 n_catalog_entries = 0;
153 wxDateTime ed = chart->GetEditionDate();
154 m_chart_date_binary = (uint32_t)ed.IsValid() ? ed.GetTicks() : 0;
155 m_chartfile_date_binary = ::wxFileModificationTime(chart->GetFullPath());
157 (uint32_t)wxFileName::GetSize(chart->GetFullPath()).GetLo();
158 m_ChartPath = chart->GetFullPath();
160 m_CompressedCacheFilePath = CompressedCachePath(chart->GetFullPath());
165 m_catalogCorrupted =
false;
171 for (
int i = 0; i < N_COLOR_SCHEMES; i++) {
172 for (
int j = 0; j < MAX_TEX_LEVEL; j++) {
173 m_cache[i][j] = NULL;
179 if (!pBSBChart)
return;
181 m_size_X = pBSBChart->GetSize_X();
182 m_size_Y = pBSBChart->GetSize_Y();
185 m_tex_dim = g_GLOptions.m_iTextureDimension;
186 m_nx_tex = (m_size_X / m_tex_dim) + ((m_size_X % m_tex_dim) == 0 ? 0 : 1);
187 m_ny_tex = (m_size_Y / m_tex_dim) + ((m_size_Y % m_tex_dim) == 0 ? 0 : 1);
190 m_ntex = m_nx_tex * m_ny_tex;
194 m_prepared_projection_type = 0;
197glTexFactory::~glTexFactory() {
200 PurgeBackgroundCompressionPool();
202 DeleteAllDescriptors();
204 for (
int i = 0; i < N_COLOR_SCHEMES; i++) {
205 for (
int j = 0; j < MAX_TEX_LEVEL; j++) {
216 for (
int i = 0; i < m_ntex; i++)
delete m_tiles[i];
221 int array_index = ArrayIndex(rect.x, rect.y);
222 return m_td_array[array_index];
225bool glTexFactory::OnTimer() {
226 for (
int i = 0; i < m_ntex; i++) {
231 if (ptd && ptd->compdata_ticks) {
232 ptd->compdata_ticks--;
240 if(g_GLOptions.m_bTextureCompression) {
245 for(
int y = 0; y<m_ny_tex; y++) {
246 int dim = g_GLOptions.m_iTextureDimension;
248 if(!pBSBChart->HaveLineCacheRow(y*dim))
251 for(
int x = 0; x<m_nx_tex; x++) {
252 int i = ArrayIndex(x, y);
258 if( ptd->compcomp_array[0] )
266 pBSBChart->FreeLineCacheRows(y*dim, (y+1)*dim);
274 if (g_GLOptions.m_bTextureCompressionCaching)
275 for (
int i = 0; i < m_ntex; i++) {
277 if (ptd && ptd->IsCompCompArrayComplete(0)) {
278 int dim = g_GLOptions.m_iTextureDimension;
279 UpdateCacheAllLevels(wxRect(ptd->x, ptd->y, dim, dim),
280 ptd->m_colorscheme, ptd->compcomp_array,
296 bool bGLMemCrunch = g_tex_mem_used > 30 * 1024 * 1024;
299 for(wxTextureListNode *node = m_texture_list.GetFirst(); node;
300 node = node->GetNext()) {
302 if(ptd->nGPU_compressed == GPU_TEXTURE_UNCOMPRESSED){
303 DeleteSingleTexture(ptd);
310void glTexFactory::AccumulateMemStatistics(
int &map_size,
int &comp_size,
311 int &compcomp_size) {
312 for (
int i = 0; i < m_ntex; i++) {
315 map_size += ptd->GetMapArrayAlloc();
316 comp_size += ptd->GetCompArrayAlloc();
317 compcomp_size += ptd->GetCompCompArrayAlloc();
322void glTexFactory::DeleteTexture(
const wxRect &rect) {
324 int array_index = ArrayIndex(rect.x, rect.y);
327 if (ptd && ptd->tex_name > 0) {
328 DeleteSingleTexture(ptd);
332void glTexFactory::DeleteAllTextures() {
337 for (
int i = 0; i < m_ntex; i++) {
346 DeleteSingleTexture(ptd);
351void glTexFactory::DeleteSomeTextures(
long target) {
357 for (
int i = 0; i < m_ntex; i++) {
366 if (ptd->tex_name) DeleteSingleTexture(ptd);
368 if (g_tex_mem_used <= target)
break;
373void glTexFactory::FreeSome(
long target) {
374 for (
int i = 0; i < m_ntex; i++) {
377 if (ptd) ptd->FreeMap();
381void glTexFactory::DeleteAllDescriptors() {
384 for (
int i = 0; i < m_ntex; i++) {
391bool glTexFactory::BackgroundCompressionAsJob()
const {
395void glTexFactory::PurgeBackgroundCompressionPool() {
401 if (!ptd->tex_name)
return;
403 g_tex_mem_used -= ptd->tex_mem_used;
406 glDeleteTextures(1, &ptd->tex_name);
408 ptd->tex_mem_used = 0;
409 ptd->nGPU_compressed = GPU_TEXTURE_UNKNOWN;
412void glTexFactory::ArrayXY(wxRect *r,
int index)
const {
413 r->y = (index / m_stride) * m_tex_dim;
414 r->x = (index - ((r->y / m_tex_dim) * m_stride)) * m_tex_dim;
418 ColorScheme color_scheme) {
419 if (level < 0 || level >= MAX_TEX_LEVEL)
return 0;
425 if (v == 0)
return 0;
427 int array_index = ArrayIndex(x, y);
428 if (array_index >= m_ntex)
return 0;
431 if (r->compressed_size == 0)
return 0;
436bool glTexFactory::IsLevelInCache(
int level,
const wxRect &rect,
437 ColorScheme color_scheme) {
440 if (g_GLOptions.m_bTextureCompression &&
441 g_GLOptions.m_bTextureCompressionCaching) {
443 if (GetCacheEntryValue(level, rect.x, rect.y, color_scheme) != 0)
451 int array_index = ArrayIndex(rect.x, rect.y);
452 if (!m_td_array[array_index]) {
458 p->m_colorscheme = global_color_scheme;
459 m_td_array[array_index] = p;
461 return m_td_array[array_index];
464static void CreateTexture(GLuint &tex_name,
bool b_use_mipmaps) {
465 glGenTextures(1, &tex_name);
469 glBindTexture(GL_TEXTURE_2D, tex_name);
471 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
477 GL_LINEAR_MIPMAP_LINEAR);
479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
488 const wxRect &rect) {
489 bool busy_shown =
false;
496 bool b_use_compressed_mipmaps =
false;
497 bool b_use_uncompressed_mipmaps =
false;
499 bool b_use_compressed_mipmaps =
true;
502 bool b_use_uncompressed_mipmaps = !g_GLOptions.m_bTextureCompression;
515 b_lowmem = g_GLOptions.m_bTextureCompression;
517 if (g_GLOptions.m_bTextureCompression &&
518 ptd->nGPU_compressed == GPU_TEXTURE_UNCOMPRESSED) {
520 if (ptd->comp_array[base_level]) DeleteSingleTexture(ptd);
524 if (base_level == ptd->level_min)
return false;
526 if (base_level > ptd->level_min) {
530 bool b_use_mipmaps = ptd->nGPU_compressed == GPU_TEXTURE_COMPRESSED
531 ? b_use_compressed_mipmaps
532 : b_use_uncompressed_mipmaps;
537 (double)(g_GLOptions.m_iTextureMemorySize * 1024 * 1024) * factor;
538 if (!bGLMemCrunch)
return false;
542 int status = GetTextureLevel(ptd, rect, base_level, ptd->m_colorscheme);
544 bool b_use_mipmaps = COMPRESSED_BUFFER_OK == status
545 ? b_use_compressed_mipmaps
546 : b_use_uncompressed_mipmaps;
548 DeleteSingleTexture(ptd);
549 CreateTexture(ptd->tex_name, b_use_mipmaps);
550 ptd->nGPU_compressed = COMPRESSED_BUFFER_OK == status
551 ? GPU_TEXTURE_COMPRESSED
552 : GPU_TEXTURE_UNCOMPRESSED;
554 if (COMPRESSED_BUFFER_OK == status) {
555 int texture_level = 0;
556 for (
int level = base_level; level < ptd->level_min; level++) {
557 int size = TextureTileSize(level,
true);
558 int status = GetTextureLevel(ptd, rect, level, ptd->m_colorscheme);
559 int dim = TextureDim(level);
560 glCompressedTexImage2D(GL_TEXTURE_2D, texture_level,
g_raster_format, dim,
561 dim, 0, size, ptd->comp_array[level]);
563 ptd->tex_mem_used += size;
564 g_tex_mem_used += size;
567 if (!b_use_mipmaps)
break;
576 BasePlatform::ShowBusySpinner();
578 m_newCatalog =
false;
585 g_GLOptions.m_bTextureCompression) {
590 ptd->nGPU_compressed = GPU_TEXTURE_COMPRESSED;
591 b_use_mipmaps = b_use_compressed_mipmaps;
592 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
593 GL_LINEAR_MIPMAP_LINEAR);
597 int uc_base_level = base_level;
598 if (b_lowmem) uc_base_level++;
599 int texture_level = 0;
600 for (
int level = uc_base_level; level < ptd->level_min + b_lowmem;
602 int status = GetTextureLevel(ptd, rect, level, ptd->m_colorscheme);
603 int dim = TextureDim(level);
604 glTexImage2D(GL_TEXTURE_2D, texture_level, GL_RGB, dim, dim, 0,
605 FORMAT_BITS, GL_UNSIGNED_BYTE, ptd->map_array[level]);
606 int size = TextureTileSize(level,
false);
607 ptd->tex_mem_used += size;
608 g_tex_mem_used += size;
611 if (!b_use_mipmaps)
break;
616 ptd->level_min = base_level;
619 for (
int i = 0; i < base_level - 1; i++) {
620 free(ptd->map_array[i]);
621 ptd->map_array[i] = 0;
624 if (busy_shown) AbstractPlatform::HideBusySpinner();
629bool glTexFactory::PrepareTexture(
int base_level,
const wxRect &rect,
630 ColorScheme color_scheme,
int mem_used) {
634 ptd = GetOrCreateTD(rect);
636 ptd->m_colorscheme = color_scheme;
640 if (!BuildTexture(ptd, base_level, rect))
641 glBindTexture(GL_TEXTURE_2D, ptd->tex_name);
644 if (g_GLOptions.m_bTextureCompression &&
645 ptd->nGPU_compressed == GPU_TEXTURE_UNCOMPRESSED) {
651 glBindTexture(GL_TEXTURE_2D, ptd->tex_name);
670 if (g_memCacheLimit > 0) {
672 if(mem_used > g_memCacheLimit * 7 / 10)
675 if(mem_used > g_memCacheLimit * 9 / 10)
688 DeleteSingleTexture(ptd);
693void glTexFactory::PrepareTiles(
const ViewPort &vp,
bool use_norm_vp,
696 if (!pChartBSB)
return;
699 if (vp.m_projection_type == PROJECTION_POLAR) {
700 bool north = vp.
clat > 0;
701 if (m_north != north) m_prepared_projection_type = 0;
705 if (vp.m_projection_type == m_prepared_projection_type)
return;
707 m_prepared_projection_type = vp.m_projection_type;
711 native_scale = pChartBSB->GetNativeScale();
714 for (
int i = 0; i < m_ntex; i++)
delete m_tiles[i];
718 int tex_dim = g_GLOptions.m_iTextureDimension;
725 double xsplits, ysplits;
726 switch (vp.m_projection_type) {
727 case PROJECTION_POLAR:
728 case PROJECTION_STEREOGRAPHIC:
729 case PROJECTION_ORTHOGRAPHIC:
730 case PROJECTION_GNOMONIC:
731 case PROJECTION_POLYCONIC:
732 xsplits = native_scale / 1000000000.0 * tex_dim;
736 if (vp.m_projection_type == PROJECTION_ORTHOGRAPHIC) {
738 pChartBSB->GetChartExtent(&e);
739 xsplits = xsplits * wxMax(fabsf(e.NLAT), fabsf(e.SLAT)) / 90;
742 xsplits = round(xsplits);
743 ysplits = 2 * xsplits;
745 xsplits = wxMin(wxMax(xsplits, 1), 8);
746 ysplits = wxMin(wxMax(ysplits, 1), 8);
748 case PROJECTION_EQUIRECTANGULAR:
760 pChartBSB->chartpix_to_latlong(m_size_X / 2, m_size_Y / 2, &m_clat,
762 nvp = glChartCanvas::NormalizedViewPort(vp, m_clat, m_clon);
768 for (
int i = 0; i < m_ny_tex; i++) {
769 rect.height = tex_dim;
771 for (
int j = 0; j < m_nx_tex; j++) {
772 rect.width = tex_dim;
779 int x[4] = {rect.x, rect.x, rect.x + rect.width, rect.x + rect.width};
780 int y[4] = {rect.y + rect.height, rect.y, rect.y, rect.y + rect.height};
782 for (
int k = 0; k < 4; k++) {
783 pChartBSB->chartpix_to_latlong(x[k], y[k], &lat, &lon);
784 ll[2 * k + 0] = lon, ll[2 * k + 1] = lat;
788 float lonmin = ll[0], lonmax = ll[0];
789 float latmin = ll[1], latmax = ll[1];
790 for (
int i = 2; i < 8; i += 2) {
791 lonmin = wxMin(lonmin, ll[i]), lonmax = wxMax(lonmax, ll[i]);
792 latmin = wxMin(latmin, ll[i + 1]), latmax = wxMax(latmax, ll[i + 1]);
795 if (fabsf(lonmin - lonmax) > 180) {
796 lonmin = 540, lonmax = 0;
797 for (
int i = 0; i < 8; i += 2) {
798 float lon = ll[i] < 0 ? ll[i] + 360 : ll[i];
799 lonmin = wxMin(lonmin, lon), lonmax = wxMax(lonmax, lon);
803 tile->box.Set(latmin, lonmin, latmax, lonmax);
805 double xs = rect.width / xsplits;
806 double ys = rect.height / ysplits;
807 double x1 = rect.x, u1 = 0;
809 int maxncoords = 4 * xsplits * ysplits;
810 tile->m_coords =
new float[2 * maxncoords];
811 tile->m_texcoords =
new float[2 * maxncoords];
817 for (
int x = 0; x < xsplits; x++) {
818 double x2 = wxMin(x1 + xs, m_size_X - end);
819 double u2 = (x2 - rect.x) / rect.width;
821 double y1 = rect.y, v1 = 0;
822 for (
int y = 0; y < ysplits; y++) {
823 double y2 = wxMin(y1 + ys, m_size_Y - end);
824 double v2 = (y2 - rect.y) / rect.height;
827 double xc[4] = {x1, x1, x2, x2}, yc[4] = {y2, y1, y1, y2};
828 double lat[4], lon[4];
829 for (
int k = 0; k < 4; k++) {
830 pChartBSB->chartpix_to_latlong(xc[k], yc[k], lat + k, lon + k);
833 double u[4] = {u1, u1, u2, u2}, v[4] = {v2, v1, v1, v2};
834 for (
int j = 0; j < 4; j++) {
835 int idx = 2 * tile->m_ncoords;
836 tile->m_texcoords[idx + 0] = u[j];
837 tile->m_texcoords[idx + 1] = v[j];
841 tile->m_coords[idx + 0] = p.m_x;
842 tile->m_coords[idx + 1] = p.m_y;
844 tile->m_coords[idx + 0] = lat[j];
845 tile->m_coords[idx + 1] = lon[j];
850 if (y1 + ys > m_size_Y - end)
break;
855 if (x1 + xs > m_size_X - end)
break;
860 rect.x += rect.width;
862 rect.y += rect.height;
866bool glTexFactory::UpdateCacheLevel(
const wxRect &rect,
int level,
867 ColorScheme color_scheme,
868 unsigned char *data,
int size) {
869 if (!g_GLOptions.m_bTextureCompressionCaching)
return false;
871 if (!data)
return false;
876 GetCacheEntryValue(level, rect.x, rect.y, color_scheme);
879 if (v != 0)
return false;
881 return UpdateCachePrecomp(data, size, rect, level, color_scheme);
884bool glTexFactory::UpdateCacheAllLevels(
const wxRect &rect,
885 ColorScheme color_scheme,
886 unsigned char **compcomp_array,
887 int *compcomp_size) {
888 if (!g_GLOptions.m_bTextureCompressionCaching)
return false;
893 work |= UpdateCacheLevel(rect, level, color_scheme, compcomp_array[level],
894 compcomp_size[level]);
896 WriteCatalogAndHeader();
903 int level, ColorScheme color_scheme) {
905 if (g_GLOptions.m_bTextureCompression) {
906 if (ptd->comp_array[level])
return COMPRESSED_BUFFER_OK;
907 if (ptd->compcomp_array[level]) {
909 int size = TextureTileSize(level,
true);
910 unsigned char *cb = (
unsigned char *)malloc(size);
911 LZ4_decompress_fast((
char *)ptd->compcomp_array[level], (
char *)cb, size);
912 ptd->comp_array[level] = cb;
913 return COMPRESSED_BUFFER_OK;
914 }
else if (g_GLOptions.m_bTextureCompressionCaching) {
919 GetCacheEntryValue(level, rect.x, rect.y, color_scheme);
924 int size = TextureTileSize(level,
true);
926 if (m_fs->IsOpened()) {
927 m_fs->Seek(p->texture_offset);
928 ptd->comp_array[level] = (
unsigned char *)malloc(size);
929 int max_compressed_size = LZ4_COMPRESSBOUND(g_tile_size);
930 char *compressed_data = (
char *)malloc(p->compressed_size);
931 m_fs->Read(compressed_data, p->compressed_size);
932 LZ4_decompress_fast(compressed_data, (
char *)ptd->comp_array[level],
934 free(compressed_data);
937 return COMPRESSED_BUFFER_OK;
944 if (!ptd->map_array[level]) GetFullMap(ptd, rect, m_ChartPath, level);
946 return MAP_BUFFER_OK;
952bool glTexFactory::LoadHeader() {
953 if (m_hdrOK)
return true;
955 bool need_new =
false;
957 if (wxFileName::FileExists(m_CompressedCacheFilePath)) {
958 m_fs =
new wxFFile(m_CompressedCacheFilePath,
"rb+");
959 if (m_fs->IsOpened()) {
963 wxFileOffset hdr_offset = m_fs->Length() -
sizeof(hdr);
964 hdr_offset = m_fs->Seek(hdr_offset);
966 if (
sizeof(hdr) == m_fs->Read(&hdr,
sizeof(hdr))) {
967 if (hdr.magic != COMPRESSED_CACHE_MAGIC ||
968 hdr.chartdate != m_chart_date_binary ||
969 hdr.chartfile_date != m_chartfile_date_binary ||
970 hdr.chartfile_size != m_chartfile_size ||
976 n_catalog_entries = hdr.m_nentries;
977 m_catalog_offset = hdr.catalog_offset;
980 n_catalog_entries = 0;
981 m_catalog_offset = 0;
982 WriteCatalogAndHeader();
989 wxRemoveFile(m_CompressedCacheFilePath);
995 wxFileName fn(m_CompressedCacheFilePath);
996 if (!fn.DirExists()) fn.Mkdir();
1002 m_fs =
new wxFFile(m_CompressedCacheFilePath,
"wb");
1003 n_catalog_entries = 0;
1004 m_catalog_offset = 0;
1005 WriteCatalogAndHeader();
1008 m_fs =
new wxFFile(m_CompressedCacheFilePath,
"rb+");
1014bool glTexFactory::AddCacheEntryValue(
const CatalogEntry &p) {
1015 if ((
int)p.k.tcolorscheme < 0 || p.k.tcolorscheme >= N_COLOR_SCHEMES)
1018 if (p.k.mip_level < 0 || p.k.mip_level >= MAX_TEX_LEVEL)
return false;
1020 int array_index = ArrayIndex(p.k.x, p.k.y);
1021 if (array_index < 0 || array_index >= m_ntex)
return false;
1023 if (m_cache[p.k.tcolorscheme][p.k.mip_level] == 0)
1024 m_cache[p.k.tcolorscheme][p.k.mip_level] =
1033bool glTexFactory::LoadCatalog() {
1034 m_newCatalog =
false;
1035 if (m_catalogOK)
return true;
1037 if (!LoadHeader())
return false;
1039 if (n_catalog_entries == 0) {
1042 m_newCatalog =
true;
1046 m_fs->Seek(m_catalog_offset);
1049 int buf_size = ps.GetSerialSize();
1050 unsigned char *buf = (
unsigned char *)malloc(buf_size);
1054 for (
int i = 0; i < n_catalog_entries; i++) {
1055 m_fs->Read(buf, buf_size);
1057 if (!AddCacheEntryValue(p)) bad =
true;
1061 if (bad && !m_catalogCorrupted) {
1062 wxLogMessage(
"Bad cache catalog %s %s", m_ChartPath.c_str(),
1063 m_CompressedCacheFilePath.c_str());
1064 m_catalogCorrupted =
true;
1070bool glTexFactory::WriteCatalogAndHeader() {
1071 if (m_fs && m_fs->IsOpened()) {
1072 m_fs->Seek(m_catalog_offset);
1075 int buf_size = ps.GetSerialSize();
1076 unsigned char buf[CATALOG_ENTRY_SERIAL_SIZE];
1078 int new_n_catalog_entries = 0;
1081 for (
int i = 0; i < N_COLOR_SCHEMES; i++) {
1082 p.k.tcolorscheme = (ColorScheme)i;
1083 for (
int j = 0; j < MAX_TEX_LEVEL; j++) {
1087 for (
int k = 0; k < m_ntex; k++) {
1092 if (r->compressed_size == 0)
continue;
1094 new_n_catalog_entries++;
1096 m_fs->Write(buf, buf_size);
1101 n_catalog_entries = new_n_catalog_entries;
1104 hdr.magic = COMPRESSED_CACHE_MAGIC;
1106 hdr.m_nentries = n_catalog_entries;
1107 hdr.catalog_offset = m_catalog_offset;
1108 hdr.chartdate = m_chart_date_binary;
1109 hdr.chartfile_date = m_chartfile_date_binary;
1110 hdr.chartfile_size = m_chartfile_size;
1112 m_fs->Write(&hdr,
sizeof(hdr));
1120bool glTexFactory::UpdateCachePrecomp(
unsigned char *data,
int data_size,
1121 const wxRect &rect,
int level,
1122 ColorScheme color_scheme,
1123 bool write_catalog) {
1124 if (level < 0 || level >= MAX_TEX_LEVEL)
return false;
1127 if (GetCacheEntryValue(level, rect.x, rect.y, color_scheme) != 0)
1131 wxASSERT(m_fs != 0);
1133 if (!m_fs->IsOpened())
return false;
1139 p.v.texture_offset = m_catalog_offset;
1141 p.v.compressed_size = data_size;
1142 AddCacheEntryValue(p);
1143 n_catalog_entries++;
1147 m_fs->Seek(m_catalog_offset);
1148 m_fs->Write(data, data_size);
1152 m_catalog_offset += data_size;
1153 if (write_catalog) WriteCatalogAndHeader();
General chart base definitions.
ChartDB * ChartData
Global instance.
Charts database management
Generic Chart canvas base.
Base class for BSB (Maptech/NOS) format nautical charts.
Base class for all chart types.
ViewPort - Core geographic projection and coordinate transformation engine.
wxPoint2DDouble GetDoublePixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates with double precision.
double clat
Center latitude of the viewport in degrees.
Global variables stored in configuration file.
GLuint g_raster_format
Global instance.
OpenGL chart rendering canvas.
glTextureManager * g_glTextureManager
Global instance.
OpenGL texture container.
int g_mipmap_max_level
Global instance.
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
Geographic projection and coordinate transformations.