void glTextureManager::BuildCompressedCache() { idx_sorted_by_distance.Clear(); // Building the cache may take a long time.... // Be a little smarter. // Build a sorted array of chart database indices, sorted on distance from the ownship currently. // This way, a user may build a few charts textures for immediate use, then "skip" out on the rest until later. int count = 0; for(int i = 0; i<ChartData->GetChartTableEntries(); i++) { /* skip if not kap */ const ChartTableEntry &cte = ChartData->GetChartTableEntry(i); ChartTypeEnum chart_type = (ChartTypeEnum)cte.GetChartType(); if(chart_type != CHART_TYPE_KAP) continue; wxString CompressedCacheFilePath = CompressedCachePath(ChartData->GetDBChartFileName(i)); wxFileName fn(CompressedCacheFilePath); // if(fn.FileExists()) /* skip if file exists */ // continue; idx_sorted_by_distance.Add(i); count++; } if(count == 0) return; wxLogMessage(wxString::Format(_T("BuildCompressedCache() count = %d"), count )); b_inCompressAllCharts = true; PurgeJobList(); ClearAllRasterTextures(); // Build another array of sorted compression targets. // We need to do this, as the chart table will not be invariant // after the compression threads start, so our index array will be invalid. ArrayOfCompressTargets ct_array; for(unsigned int j = 0; j<idx_sorted_by_distance.GetCount(); j++) { int i = idx_sorted_by_distance.Item(j); const ChartTableEntry &cte = ChartData->GetChartTableEntry(i); double distance = chart_dist(i); wxString filename(cte.GetpFullPath(), wxConvUTF8); compress_target *pct = new compress_target; pct->distance = distance; pct->chart_path = filename; ct_array.Add(pct); } // create progress dialog long style = wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_CAN_SKIP; wxString msg0; msg0 = _T(" \n \n "); #ifdef __WXQT__ msg0 = _T("Very longgggggggggggggggggggggggggggggggggggggggggggg\ngggggggggggggggggggggggggggggggggggggggggggg top line "); #endif for(int i=0 ; i < m_max_jobs+1 ; i++) msg0 += _T("\n "); m_progDialog = new wxGenericProgressDialog(); wxFont *qFont = GetOCPNScaledFont(_("Dialog")); int fontSize = qFont->GetPointSize(); wxFont *sFont; wxSize csz = cc1->GetClientSize(); if(csz.x < 500 || csz.y < 500) sFont = FontMgr::Get().FindOrCreateFont( 10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); else sFont = FontMgr::Get().FindOrCreateFont( fontSize, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); m_progDialog->SetFont( *sFont ); // Should we use "compact" screen layout? wxScreenDC sdc; int height, width; sdc.GetTextExtent(_T("[WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW]"), &width, &height, NULL, NULL, sFont); if(width > (csz.x / 2)) m_bcompact = true; m_progDialog->Create(_("OpenCPN Compressed Cache Update"), msg0, count+1, NULL, style ); // Make sure the dialog is big enough to be readable m_progDialog->Hide(); wxSize sz = m_progDialog->GetSize(); sz.x = csz.x * 9 / 10; m_progDialog->SetSize( sz ); m_progDialog->Layout(); wxSize sza = m_progDialog->GetSize(); wxSize pprog_size = sz; m_progDialog->Centre(); m_progDialog->Show(); m_progDialog->Raise(); m_skipout = false; m_skip = false; for( m_jcnt = 0; m_jcnt<ct_array.GetCount(); m_jcnt++) { wxString filename = ct_array.Item(m_jcnt).chart_path; wxString CompressedCacheFilePath = CompressedCachePath(filename); double distance = ct_array.Item(m_jcnt).distance; ChartBase *pchart = ChartData->OpenChartFromDBAndLock( filename, FULL_INIT ); if(!pchart) /* probably a corrupt chart */ continue; // bad things if more than one texfactory for a chart g_glTextureManager->PurgeChartTextures( pchart, true ); ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart ); if(pBSBChart) { glTexFactory *tex_fact = new glTexFactory(pchart, g_raster_format); m_progMsg.Printf( _("Distance from Ownship: %4.0f NMi\n"), distance); m_progMsg.Prepend(_T("Preparing RNC Cache...\n")); if(m_skipout) { g_glTextureManager->PurgeJobList(); ChartData->DeleteCacheChart(pchart); delete tex_fact; break; } int size_X = pBSBChart->GetSize_X(); int size_Y = pBSBChart->GetSize_Y(); int tex_dim = g_GLOptions.m_iTextureDimension; int nx_tex = ceil( (float)size_X / tex_dim ); int ny_tex = ceil( (float)size_Y / tex_dim ); int nt = ny_tex * nx_tex; wxRect rect; rect.y = 0; rect.width = tex_dim; rect.height = tex_dim; for( int y = 0; y < ny_tex; y++ ) { rect.x = 0; for( int x = 0; x < nx_tex; x++ ) { for(int level = 0; level < g_mipmap_max_level + 1; level++ ) if(!tex_fact->IsLevelInCache( level, rect, global_color_scheme )){ goto schedule; } rect.x += rect.width; } rect.y += rect.height; } // Free all possible memory ChartData->DeleteCacheChart(pchart); delete tex_fact; continue; schedule: ScheduleJob(tex_fact, wxRect(), 0, false, true, true, false); while(!m_skip) { ::wxYield(); int cnt = GetJobCount() - GetRunningJobCount(); if(!cnt) break; wxThread::Sleep(1); } if(m_skipout) { g_glTextureManager->PurgeJobList(); ChartData->DeleteCacheChart(pchart); delete tex_fact; break; } } } while(GetRunningJobCount()) { wxThread::Sleep(1); ::wxYield(); } b_inCompressAllCharts = false; delete m_progDialog; m_progDialog = NULL; }
void BuildCompressedCache() { idx_sorted_by_distance.Clear(); // Building the cache may take a long time.... // Be a little smarter. // Build a sorted array of chart database indices, sorted on distance from the ownship currently. // This way, a user may build a few charts textures for immediate use, then "skip" out on the rest until later. int count = 0; for(int i = 0; i<ChartData->GetChartTableEntries(); i++) { /* skip if not kap */ const ChartTableEntry &cte = ChartData->GetChartTableEntry(i); ChartTypeEnum chart_type = (ChartTypeEnum)cte.GetChartType(); if(chart_type != CHART_TYPE_KAP) continue; wxString CompressedCacheFilePath = CompressedCachePath(ChartData->GetDBChartFileName(i)); wxFileName fn(CompressedCacheFilePath); // if(fn.FileExists()) /* skip if file exists */ // continue; idx_sorted_by_distance.Add(i); count++; } if(count == 0) return; wxLogMessage(wxString::Format(_T("BuildCompressedCache() count = %d"), count )); b_inCompressAllCharts = true; g_glTextureManager->PurgeJobList(); g_glTextureManager->ClearAllRasterTextures(); // Build another array of sorted compression targets. // We need to do this, as the chart table will not be invariant // after the compression threads start, so our index array will be invalid. ArrayOfCompressTargets ct_array; for(unsigned int j = 0; j<idx_sorted_by_distance.GetCount(); j++) { int i = idx_sorted_by_distance.Item(j); const ChartTableEntry &cte = ChartData->GetChartTableEntry(i); double distance = chart_dist(i); wxString filename(cte.GetpFullPath(), wxConvUTF8); compress_target *pct = new compress_target; pct->distance = distance; pct->chart_path = filename; ct_array.Add(pct); } // create progress dialog long style = wxPD_SMOOTH | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_CAN_SKIP; // style |= wxSTAY_ON_TOP; wxString msg0; #ifdef __WXQT__ msg0 = _T("Very longgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg top line "); #endif wxProgressDialog prog(_("OpenCPN Compressed Cache Update"), msg0, count+1, cc1, style ); wxSize csz = cc1->GetClientSize(); if(csz.x < 600 || csz.y < 600){ wxFont *qFont = GetOCPNScaledFont(_("Dialog")); // to get type, weight, etc... wxFont *sFont = FontMgr::Get().FindOrCreateFont( 10, qFont->GetFamily(), qFont->GetStyle(), qFont->GetWeight()); prog.SetFont( *sFont ); } // Make sure the dialog is big enough to be readable prog.Hide(); wxSize sz = prog.GetSize(); sz.x = csz.x * 8 / 10; // sz.y += thread_count * 40; // allow for multiline messages prog.SetSize( sz ); wxSize pprog_size = sz; prog.Centre(); prog.Show(); prog.Raise(); bool b_skipout = false; for(unsigned int j = 0; j<ct_array.GetCount(); j++) { wxString filename = ct_array.Item(j).chart_path; wxString CompressedCacheFilePath = CompressedCachePath(filename); double distance = ct_array.Item(j).distance; ChartBase *pchart = ChartData->OpenChartFromDBAndLock( filename, FULL_INIT ); if(!pchart) /* probably a corrupt chart */ continue; // bad things if more than one texfactory for a chart g_glTextureManager->PurgeChartTextures( pchart, true ); // msgt.Printf( _T("Starting chart compression on thread %d, count %d "), t, pprog_count); ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart ); if(pBSBChart) { glTexFactory *tex_fact = new glTexFactory(pchart, g_raster_format); bool skip = false; wxString msg; msg.Printf( _("Distance from Ownship: %4.0f NMi"), distance); if(pprog_size.x > 600){ msg += _T(" Chart:"); msg += pchart->GetFullPath(); } // wxString cntmsg = wxString::Format(_T("%04d/%04d "), 0, origcnt); prog.Update(j, msg, &skip ); prog.SetSize(pprog_size); if(skip) { g_glTextureManager->PurgeJobList(); ChartData->DeleteCacheChart(pchart); delete tex_fact; break; } int size_X = pBSBChart->GetSize_X(); int size_Y = pBSBChart->GetSize_Y(); int tex_dim = g_GLOptions.m_iTextureDimension; int nx_tex = ceil( (float)size_X / tex_dim ); int ny_tex = ceil( (float)size_Y / tex_dim ); int nt = ny_tex * nx_tex; wxRect rect; rect.y = 0; rect.width = tex_dim; rect.height = tex_dim; for( int y = 0; y < ny_tex; y++ ) { rect.x = 0; for( int x = 0; x < nx_tex; x++ ) { for(int level = 0; level < g_mipmap_max_level + 1; level++ ) if(!tex_fact->IsLevelInCache( level, rect, global_color_scheme )) goto schedule; rect.x += rect.width; } rect.y += rect.height; } // Free all possible memory ChartData->DeleteCacheChart(pchart); delete tex_fact; continue; schedule: g_glTextureManager->ScheduleJob(tex_fact, wxRect(), 0, false, true, true, false); while(!skip) { ::wxYield(); int cnt = g_glTextureManager->GetJobCount() - g_glTextureManager->GetRunningJobCount(); if(!cnt) break; wxThread::Sleep(1); } } } while(g_glTextureManager->GetRunningJobCount()) { wxThread::Sleep(1); ::wxYield(); } b_inCompressAllCharts = false; }