28#include <wx/tokenzr.h>
29#include <wx/filename.h>
34#include "mipmap/mipmap.h"
48#include "OCPNPlatform.h"
53#ifndef GL_ETC1_RGB8_OES
54#define GL_ETC1_RGB8_OES 0x8D64
59typedef void (*PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers);
60typedef void (*PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
61typedef void (*PFNGLDELETEBUFFERSPROC)(GLsizei n,
const GLuint *buffers);
62typedef void (*PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname,
64typedef void (*PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n,
65 const GLuint *renderbuffers);
66typedef void (*PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n,
67 const GLuint *framebuffers);
68typedef void (*PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level,
69 GLint xoffset, GLsizei width,
73typedef void (*PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level,
75typedef GLenum (*PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
76typedef void (*PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target,
78typedef void (*PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size,
79 const GLvoid *data, GLenum usage);
80typedef void (*PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint *framebuffers);
81typedef void (*PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint *renderbuffers);
82typedef void (*PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target,
85 GLuint texture, GLint level);
86typedef void (*PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level,
87 GLenum internalformat,
88 GLsizei width, GLsizei height,
89 GLint border, GLsizei imageSize,
91typedef void (*PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target,
93 GLenum renderbuffertarget,
95typedef void (*PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target,
96 GLenum internalformat,
97 GLsizei width, GLsizei height);
98typedef void (*PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
101extern ColorScheme global_color_scheme;
105extern bool GetMemoryStatus(
int *mem_total,
int *mem_used);
109extern wxString CompressedCachePath(wxString path);
112CatalogEntry::CatalogEntry() {}
114CatalogEntry::~CatalogEntry() {}
116CatalogEntry::CatalogEntry(
int level,
int x0,
int y0, ColorScheme colorscheme) {
120 k.tcolorscheme = colorscheme;
123int CatalogEntry::GetSerialSize() {
return CATALOG_ENTRY_SERIAL_SIZE; }
125void CatalogEntry::Serialize(
unsigned char *t) {
126 uint32_t *p = (uint32_t *)t;
131 *p++ = k.tcolorscheme;
132 *p++ = v.texture_offset;
133 *p++ = v.compressed_size;
136void CatalogEntry::DeSerialize(
unsigned char *t) {
137 uint32_t *p = (uint32_t *)t;
142 k.tcolorscheme = (ColorScheme)*p++;
143 v.texture_offset = *p++;
144 v.compressed_size = *p++;
148enum TextureDataType { COMPRESSED_BUFFER_OK, MAP_BUFFER_OK };
150glTexFactory::glTexFactory(
ChartBase *chart,
int raster_format) {
152 n_catalog_entries = 0;
154 wxDateTime ed = chart->GetEditionDate();
155 m_chart_date_binary = (uint32_t)ed.IsValid() ? ed.GetTicks() : 0;
156 m_chartfile_date_binary = ::wxFileModificationTime(chart->GetFullPath());
158 (uint32_t)wxFileName::GetSize(chart->GetFullPath()).GetLo();
159 m_ChartPath = chart->GetFullPath();
161 m_CompressedCacheFilePath = CompressedCachePath(chart->GetFullPath());
166 m_catalogCorrupted =
false;
172 for (
int i = 0; i < N_COLOR_SCHEMES; i++) {
173 for (
int j = 0; j < MAX_TEX_LEVEL; j++) {
174 m_cache[i][j] = NULL;
180 if (!pBSBChart)
return;
182 m_size_X = pBSBChart->GetSize_X();
183 m_size_Y = pBSBChart->GetSize_Y();
186 m_tex_dim = g_GLOptions.m_iTextureDimension;
187 m_nx_tex = (m_size_X / m_tex_dim) + ((m_size_X % m_tex_dim) == 0 ? 0 : 1);
188 m_ny_tex = (m_size_Y / m_tex_dim) + ((m_size_Y % m_tex_dim) == 0 ? 0 : 1);
191 m_ntex = m_nx_tex * m_ny_tex;
195 m_prepared_projection_type = 0;
198glTexFactory::~glTexFactory() {
201 PurgeBackgroundCompressionPool();
203 DeleteAllDescriptors();
205 for (
int i = 0; i < N_COLOR_SCHEMES; i++) {
206 for (
int j = 0; j < MAX_TEX_LEVEL; j++) {
217 for (
int i = 0; i < m_ntex; i++)
delete m_tiles[i];
222 int array_index = ArrayIndex(rect.x, rect.y);
223 return m_td_array[array_index];
226bool glTexFactory::OnTimer() {
227 for (
int i = 0; i < m_ntex; i++) {
232 if (ptd && ptd->compdata_ticks) {
233 ptd->compdata_ticks--;
241 if(g_GLOptions.m_bTextureCompression) {
246 for(
int y = 0; y<m_ny_tex; y++) {
247 int dim = g_GLOptions.m_iTextureDimension;
249 if(!pBSBChart->HaveLineCacheRow(y*dim))
252 for(
int x = 0; x<m_nx_tex; x++) {
253 int i = ArrayIndex(x, y);
259 if( ptd->compcomp_array[0] )
267 pBSBChart->FreeLineCacheRows(y*dim, (y+1)*dim);
275 if (g_GLOptions.m_bTextureCompressionCaching)
276 for (
int i = 0; i < m_ntex; i++) {
278 if (ptd && ptd->IsCompCompArrayComplete(0)) {
279 int dim = g_GLOptions.m_iTextureDimension;
280 UpdateCacheAllLevels(wxRect(ptd->x, ptd->y, dim, dim),
281 ptd->m_colorscheme, ptd->compcomp_array,
297 bool bGLMemCrunch = g_tex_mem_used > 30 * 1024 * 1024;
300 for(wxTextureListNode *node = m_texture_list.GetFirst(); node;
301 node = node->GetNext()) {
303 if(ptd->nGPU_compressed == GPU_TEXTURE_UNCOMPRESSED){
304 DeleteSingleTexture(ptd);
311void glTexFactory::AccumulateMemStatistics(
int &map_size,
int &comp_size,
312 int &compcomp_size) {
313 for (
int i = 0; i < m_ntex; i++) {
316 map_size += ptd->GetMapArrayAlloc();
317 comp_size += ptd->GetCompArrayAlloc();
318 compcomp_size += ptd->GetCompCompArrayAlloc();
323void glTexFactory::DeleteTexture(
const wxRect &rect) {
325 int array_index = ArrayIndex(rect.x, rect.y);
328 if (ptd && ptd->tex_name > 0) {
329 DeleteSingleTexture(ptd);
333void glTexFactory::DeleteAllTextures(
void) {
338 for (
int i = 0; i < m_ntex; i++) {
347 DeleteSingleTexture(ptd);
352void glTexFactory::DeleteSomeTextures(
long target) {
358 for (
int i = 0; i < m_ntex; i++) {
367 if (ptd->tex_name) DeleteSingleTexture(ptd);
369 if (g_tex_mem_used <= target)
break;
374void glTexFactory::FreeSome(
long target) {
375 for (
int i = 0; i < m_ntex; i++) {
378 if (ptd) ptd->FreeMap();
382void glTexFactory::DeleteAllDescriptors(
void) {
385 for (
int i = 0; i < m_ntex; i++) {
392bool glTexFactory::BackgroundCompressionAsJob()
const {
396void glTexFactory::PurgeBackgroundCompressionPool() {
402 if (!ptd->tex_name)
return;
404 g_tex_mem_used -= ptd->tex_mem_used;
407 glDeleteTextures(1, &ptd->tex_name);
409 ptd->tex_mem_used = 0;
410 ptd->nGPU_compressed = GPU_TEXTURE_UNKNOWN;
413void glTexFactory::ArrayXY(wxRect *r,
int index)
const {
414 r->y = (index / m_stride) * m_tex_dim;
415 r->x = (index - ((r->y / m_tex_dim) * m_stride)) * m_tex_dim;
419 ColorScheme color_scheme) {
420 if (level < 0 || level >= MAX_TEX_LEVEL)
return 0;
426 if (v == 0)
return 0;
428 int array_index = ArrayIndex(x, y);
429 if (array_index >= m_ntex)
return 0;
432 if (r->compressed_size == 0)
return 0;
437bool glTexFactory::IsLevelInCache(
int level,
const wxRect &rect,
438 ColorScheme color_scheme) {
441 if (g_GLOptions.m_bTextureCompression &&
442 g_GLOptions.m_bTextureCompressionCaching) {
444 if (GetCacheEntryValue(level, rect.x, rect.y, color_scheme) != 0)
452 int array_index = ArrayIndex(rect.x, rect.y);
453 if (!m_td_array[array_index]) {
459 p->m_colorscheme = global_color_scheme;
460 m_td_array[array_index] = p;
462 return m_td_array[array_index];
465static void CreateTexture(GLuint &tex_name,
bool b_use_mipmaps) {
466 glGenTextures(1, &tex_name);
470 glBindTexture(GL_TEXTURE_2D, tex_name);
472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
477 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
478 GL_LINEAR_MIPMAP_LINEAR);
480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
484 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
489 const wxRect &rect) {
490 bool busy_shown =
false;
497 bool b_use_compressed_mipmaps =
false;
498 bool b_use_uncompressed_mipmaps =
false;
500 bool b_use_compressed_mipmaps =
true;
503 bool b_use_uncompressed_mipmaps = !g_GLOptions.m_bTextureCompression;
516 b_lowmem = g_GLOptions.m_bTextureCompression;
518 if (g_GLOptions.m_bTextureCompression &&
519 ptd->nGPU_compressed == GPU_TEXTURE_UNCOMPRESSED) {
521 if (ptd->comp_array[base_level]) DeleteSingleTexture(ptd);
525 if (base_level == ptd->level_min)
return false;
527 if (base_level > ptd->level_min) {
531 bool b_use_mipmaps = ptd->nGPU_compressed == GPU_TEXTURE_COMPRESSED
532 ? b_use_compressed_mipmaps
533 : b_use_uncompressed_mipmaps;
538 (double)(g_GLOptions.m_iTextureMemorySize * 1024 * 1024) * factor;
539 if (!bGLMemCrunch)
return false;
543 int status = GetTextureLevel(ptd, rect, base_level, ptd->m_colorscheme);
545 bool b_use_mipmaps = COMPRESSED_BUFFER_OK == status
546 ? b_use_compressed_mipmaps
547 : b_use_uncompressed_mipmaps;
549 DeleteSingleTexture(ptd);
550 CreateTexture(ptd->tex_name, b_use_mipmaps);
551 ptd->nGPU_compressed = COMPRESSED_BUFFER_OK == status
552 ? GPU_TEXTURE_COMPRESSED
553 : GPU_TEXTURE_UNCOMPRESSED;
555 if (COMPRESSED_BUFFER_OK == status) {
556 int texture_level = 0;
557 for (
int level = base_level; level < ptd->level_min; level++) {
558 int size = TextureTileSize(level,
true);
559 int status = GetTextureLevel(ptd, rect, level, ptd->m_colorscheme);
560 int dim = TextureDim(level);
561 glCompressedTexImage2D(GL_TEXTURE_2D, texture_level,
g_raster_format, dim,
562 dim, 0, size, ptd->comp_array[level]);
564 ptd->tex_mem_used += size;
565 g_tex_mem_used += size;
568 if (!b_use_mipmaps)
break;
577 BasePlatform::ShowBusySpinner();
579 m_newCatalog =
false;
586 g_GLOptions.m_bTextureCompression) {
591 ptd->nGPU_compressed = GPU_TEXTURE_COMPRESSED;
592 b_use_mipmaps = b_use_compressed_mipmaps;
593 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
594 GL_LINEAR_MIPMAP_LINEAR);
598 int uc_base_level = base_level;
599 if (b_lowmem) uc_base_level++;
600 int texture_level = 0;
601 for (
int level = uc_base_level; level < ptd->level_min + b_lowmem;
603 int status = GetTextureLevel(ptd, rect, level, ptd->m_colorscheme);
604 int dim = TextureDim(level);
605 glTexImage2D(GL_TEXTURE_2D, texture_level, GL_RGB, dim, dim, 0,
606 FORMAT_BITS, GL_UNSIGNED_BYTE, ptd->map_array[level]);
607 int size = TextureTileSize(level,
false);
608 ptd->tex_mem_used += size;
609 g_tex_mem_used += size;
612 if (!b_use_mipmaps)
break;
617 ptd->level_min = base_level;
620 for (
int i = 0; i < base_level - 1; i++) {
621 free(ptd->map_array[i]);
622 ptd->map_array[i] = 0;
625 if (busy_shown) AbstractPlatform::HideBusySpinner();
630bool glTexFactory::PrepareTexture(
int base_level,
const wxRect &rect,
631 ColorScheme color_scheme,
int mem_used) {
635 ptd = GetOrCreateTD(rect);
637 ptd->m_colorscheme = color_scheme;
641 if (!BuildTexture(ptd, base_level, rect))
642 glBindTexture(GL_TEXTURE_2D, ptd->tex_name);
645 if (g_GLOptions.m_bTextureCompression &&
646 ptd->nGPU_compressed == GPU_TEXTURE_UNCOMPRESSED) {
652 glBindTexture(GL_TEXTURE_2D, ptd->tex_name);
671 if (g_memCacheLimit > 0) {
673 if(mem_used > g_memCacheLimit * 7 / 10)
676 if(mem_used > g_memCacheLimit * 9 / 10)
689 DeleteSingleTexture(ptd);
694void glTexFactory::PrepareTiles(
const ViewPort &vp,
bool use_norm_vp,
697 if (!pChartBSB)
return;
700 if (vp.m_projection_type == PROJECTION_POLAR) {
701 bool north = vp.
clat > 0;
702 if (m_north != north) m_prepared_projection_type = 0;
706 if (vp.m_projection_type == m_prepared_projection_type)
return;
708 m_prepared_projection_type = vp.m_projection_type;
712 native_scale = pChartBSB->GetNativeScale();
715 for (
int i = 0; i < m_ntex; i++)
delete m_tiles[i];
719 int tex_dim = g_GLOptions.m_iTextureDimension;
726 double xsplits, ysplits;
727 switch (vp.m_projection_type) {
728 case PROJECTION_POLAR:
729 case PROJECTION_STEREOGRAPHIC:
730 case PROJECTION_ORTHOGRAPHIC:
731 case PROJECTION_GNOMONIC:
732 case PROJECTION_POLYCONIC:
733 xsplits = native_scale / 1000000000.0 * tex_dim;
737 if (vp.m_projection_type == PROJECTION_ORTHOGRAPHIC) {
739 pChartBSB->GetChartExtent(&e);
740 xsplits = xsplits * wxMax(fabsf(e.NLAT), fabsf(e.SLAT)) / 90;
743 xsplits = round(xsplits);
744 ysplits = 2 * xsplits;
746 xsplits = wxMin(wxMax(xsplits, 1), 8);
747 ysplits = wxMin(wxMax(ysplits, 1), 8);
749 case PROJECTION_EQUIRECTANGULAR:
761 pChartBSB->chartpix_to_latlong(m_size_X / 2, m_size_Y / 2, &m_clat,
763 nvp = glChartCanvas::NormalizedViewPort(vp, m_clat, m_clon);
769 for (
int i = 0; i < m_ny_tex; i++) {
770 rect.height = tex_dim;
772 for (
int j = 0; j < m_nx_tex; j++) {
773 rect.width = tex_dim;
780 int x[4] = {rect.x, rect.x, rect.x + rect.width, rect.x + rect.width};
781 int y[4] = {rect.y + rect.height, rect.y, rect.y, rect.y + rect.height};
783 for (
int k = 0; k < 4; k++) {
784 pChartBSB->chartpix_to_latlong(x[k], y[k], &lat, &lon);
785 ll[2 * k + 0] = lon, ll[2 * k + 1] = lat;
789 float lonmin = ll[0], lonmax = ll[0];
790 float latmin = ll[1], latmax = ll[1];
791 for (
int i = 2; i < 8; i += 2) {
792 lonmin = wxMin(lonmin, ll[i]), lonmax = wxMax(lonmax, ll[i]);
793 latmin = wxMin(latmin, ll[i + 1]), latmax = wxMax(latmax, ll[i + 1]);
796 if (fabsf(lonmin - lonmax) > 180) {
797 lonmin = 540, lonmax = 0;
798 for (
int i = 0; i < 8; i += 2) {
799 float lon = ll[i] < 0 ? ll[i] + 360 : ll[i];
800 lonmin = wxMin(lonmin, lon), lonmax = wxMax(lonmax, lon);
804 tile->box.Set(latmin, lonmin, latmax, lonmax);
806 double xs = rect.width / xsplits;
807 double ys = rect.height / ysplits;
808 double x1 = rect.x, u1 = 0;
810 int maxncoords = 4 * xsplits * ysplits;
811 tile->m_coords =
new float[2 * maxncoords];
812 tile->m_texcoords =
new float[2 * maxncoords];
818 for (
int x = 0; x < xsplits; x++) {
819 double x2 = wxMin(x1 + xs, m_size_X - end);
820 double u2 = (x2 - rect.x) / rect.width;
822 double y1 = rect.y, v1 = 0;
823 for (
int y = 0; y < ysplits; y++) {
824 double y2 = wxMin(y1 + ys, m_size_Y - end);
825 double v2 = (y2 - rect.y) / rect.height;
828 double xc[4] = {x1, x1, x2, x2}, yc[4] = {y2, y1, y1, y2};
829 double lat[4], lon[4];
830 for (
int k = 0; k < 4; k++) {
831 pChartBSB->chartpix_to_latlong(xc[k], yc[k], lat + k, lon + k);
834 double u[4] = {u1, u1, u2, u2}, v[4] = {v2, v1, v1, v2};
835 for (
int j = 0; j < 4; j++) {
836 int idx = 2 * tile->m_ncoords;
837 tile->m_texcoords[idx + 0] = u[j];
838 tile->m_texcoords[idx + 1] = v[j];
842 tile->m_coords[idx + 0] = p.m_x;
843 tile->m_coords[idx + 1] = p.m_y;
845 tile->m_coords[idx + 0] = lat[j];
846 tile->m_coords[idx + 1] = lon[j];
851 if (y1 + ys > m_size_Y - end)
break;
856 if (x1 + xs > m_size_X - end)
break;
861 rect.x += rect.width;
863 rect.y += rect.height;
867bool glTexFactory::UpdateCacheLevel(
const wxRect &rect,
int level,
868 ColorScheme color_scheme,
869 unsigned char *data,
int size) {
870 if (!g_GLOptions.m_bTextureCompressionCaching)
return false;
872 if (!data)
return false;
877 GetCacheEntryValue(level, rect.x, rect.y, color_scheme);
880 if (v != 0)
return false;
882 return UpdateCachePrecomp(data, size, rect, level, color_scheme);
885bool glTexFactory::UpdateCacheAllLevels(
const wxRect &rect,
886 ColorScheme color_scheme,
887 unsigned char **compcomp_array,
888 int *compcomp_size) {
889 if (!g_GLOptions.m_bTextureCompressionCaching)
return false;
894 work |= UpdateCacheLevel(rect, level, color_scheme, compcomp_array[level],
895 compcomp_size[level]);
897 WriteCatalogAndHeader();
904 int level, ColorScheme color_scheme) {
906 if (g_GLOptions.m_bTextureCompression) {
907 if (ptd->comp_array[level])
return COMPRESSED_BUFFER_OK;
908 if (ptd->compcomp_array[level]) {
910 int size = TextureTileSize(level,
true);
911 unsigned char *cb = (
unsigned char *)malloc(size);
912 LZ4_decompress_fast((
char *)ptd->compcomp_array[level], (
char *)cb, size);
913 ptd->comp_array[level] = cb;
914 return COMPRESSED_BUFFER_OK;
915 }
else if (g_GLOptions.m_bTextureCompressionCaching) {
920 GetCacheEntryValue(level, rect.x, rect.y, color_scheme);
925 int size = TextureTileSize(level,
true);
927 if (m_fs->IsOpened()) {
928 m_fs->Seek(p->texture_offset);
929 ptd->comp_array[level] = (
unsigned char *)malloc(size);
930 int max_compressed_size = LZ4_COMPRESSBOUND(g_tile_size);
931 char *compressed_data = (
char *)malloc(p->compressed_size);
932 m_fs->Read(compressed_data, p->compressed_size);
933 LZ4_decompress_fast(compressed_data, (
char *)ptd->comp_array[level],
935 free(compressed_data);
938 return COMPRESSED_BUFFER_OK;
945 if (!ptd->map_array[level]) GetFullMap(ptd, rect, m_ChartPath, level);
947 return MAP_BUFFER_OK;
953bool glTexFactory::LoadHeader(
void) {
954 if (m_hdrOK)
return true;
956 bool need_new =
false;
958 if (wxFileName::FileExists(m_CompressedCacheFilePath)) {
959 m_fs =
new wxFFile(m_CompressedCacheFilePath,
"rb+");
960 if (m_fs->IsOpened()) {
964 wxFileOffset hdr_offset = m_fs->Length() -
sizeof(hdr);
965 hdr_offset = m_fs->Seek(hdr_offset);
967 if (
sizeof(hdr) == m_fs->Read(&hdr,
sizeof(hdr))) {
968 if (hdr.magic != COMPRESSED_CACHE_MAGIC ||
969 hdr.chartdate != m_chart_date_binary ||
970 hdr.chartfile_date != m_chartfile_date_binary ||
971 hdr.chartfile_size != m_chartfile_size ||
977 n_catalog_entries = hdr.m_nentries;
978 m_catalog_offset = hdr.catalog_offset;
981 n_catalog_entries = 0;
982 m_catalog_offset = 0;
983 WriteCatalogAndHeader();
990 wxRemoveFile(m_CompressedCacheFilePath);
996 wxFileName fn(m_CompressedCacheFilePath);
997 if (!fn.DirExists()) fn.Mkdir();
1003 m_fs =
new wxFFile(m_CompressedCacheFilePath,
"wb");
1004 n_catalog_entries = 0;
1005 m_catalog_offset = 0;
1006 WriteCatalogAndHeader();
1009 m_fs =
new wxFFile(m_CompressedCacheFilePath,
"rb+");
1015bool glTexFactory::AddCacheEntryValue(
const CatalogEntry &p) {
1016 if ((
int)p.k.tcolorscheme < 0 || p.k.tcolorscheme >= N_COLOR_SCHEMES)
1019 if (p.k.mip_level < 0 || p.k.mip_level >= MAX_TEX_LEVEL)
return false;
1021 int array_index = ArrayIndex(p.k.x, p.k.y);
1022 if (array_index < 0 || array_index >= m_ntex)
return false;
1024 if (m_cache[p.k.tcolorscheme][p.k.mip_level] == 0)
1025 m_cache[p.k.tcolorscheme][p.k.mip_level] =
1034bool glTexFactory::LoadCatalog(
void) {
1035 m_newCatalog =
false;
1036 if (m_catalogOK)
return true;
1038 if (!LoadHeader())
return false;
1040 if (n_catalog_entries == 0) {
1043 m_newCatalog =
true;
1047 m_fs->Seek(m_catalog_offset);
1050 int buf_size = ps.GetSerialSize();
1051 unsigned char *buf = (
unsigned char *)malloc(buf_size);
1055 for (
int i = 0; i < n_catalog_entries; i++) {
1056 m_fs->Read(buf, buf_size);
1058 if (!AddCacheEntryValue(p)) bad =
true;
1062 if (bad && !m_catalogCorrupted) {
1063 wxLogMessage(
"Bad cache catalog %s %s", m_ChartPath.c_str(),
1064 m_CompressedCacheFilePath.c_str());
1065 m_catalogCorrupted =
true;
1071bool glTexFactory::WriteCatalogAndHeader() {
1072 if (m_fs && m_fs->IsOpened()) {
1073 m_fs->Seek(m_catalog_offset);
1076 int buf_size = ps.GetSerialSize();
1077 unsigned char buf[CATALOG_ENTRY_SERIAL_SIZE];
1079 int new_n_catalog_entries = 0;
1082 for (
int i = 0; i < N_COLOR_SCHEMES; i++) {
1083 p.k.tcolorscheme = (ColorScheme)i;
1084 for (
int j = 0; j < MAX_TEX_LEVEL; j++) {
1088 for (
int k = 0; k < m_ntex; k++) {
1093 if (r->compressed_size == 0)
continue;
1095 new_n_catalog_entries++;
1097 m_fs->Write(buf, buf_size);
1102 n_catalog_entries = new_n_catalog_entries;
1105 hdr.magic = COMPRESSED_CACHE_MAGIC;
1107 hdr.m_nentries = n_catalog_entries;
1108 hdr.catalog_offset = m_catalog_offset;
1109 hdr.chartdate = m_chart_date_binary;
1110 hdr.chartfile_date = m_chartfile_date_binary;
1111 hdr.chartfile_size = m_chartfile_size;
1113 m_fs->Write(&hdr,
sizeof(hdr));
1121bool glTexFactory::UpdateCachePrecomp(
unsigned char *data,
int data_size,
1122 const wxRect &rect,
int level,
1123 ColorScheme color_scheme,
1124 bool write_catalog) {
1125 if (level < 0 || level >= MAX_TEX_LEVEL)
return false;
1128 if (GetCacheEntryValue(level, rect.x, rect.y, color_scheme) != 0)
1132 wxASSERT(m_fs != 0);
1134 if (!m_fs->IsOpened())
return false;
1140 p.v.texture_offset = m_catalog_offset;
1142 p.v.compressed_size = data_size;
1143 AddCacheEntryValue(p);
1144 n_catalog_entries++;
1148 m_fs->Seek(m_catalog_offset);
1149 m_fs->Write(data, data_size);
1153 m_catalog_offset += data_size;
1154 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.