示例#1
0
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;
}
示例#2
0
int CompareInts(int n1, int n2)
{
    double d1 = chart_dist(n1);
    double d2 = chart_dist(n2);
    return (int)(d1 - d2);
}
示例#3
0
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;
}