예제 #1
0
void glTextureManager::OnEvtThread( OCPN_CompressionThreadEvent & event )
{
    JobTicket *ticket = event.GetTicket();

    if(ticket->b_isaborted || ticket->b_abort){
        for(int i=0 ; i < g_mipmap_max_level+1 ; i++) {
            free(ticket->comp_bits_array[i]);
            free( ticket->compcomp_bits_array[i] );
        }
        
        if(bthread_debug)
            printf( "    Abort job: %08X  Jobs running: %d             Job count: %lu   \n",
                    ticket->ident, GetRunningJobCount(), (unsigned long)todo_list.GetCount());
    } else if(!b_inCompressAllCharts) {
        //   Normal completion from here
        glTextureDescriptor *ptd = ticket->pFact->GetpTD( ticket->rect );
        if(ptd) {
            for(int i=0 ; i < g_mipmap_max_level+1 ; i++)
                ptd->comp_array[i] = ticket->comp_bits_array[i];

            if(ticket->bpost_zip_compress){
                for(int i=0 ; i < g_mipmap_max_level+1 ; i++){
                    ptd->compcomp_array[i] = ticket->compcomp_bits_array[i];
                    ptd->compcomp_size[i] = ticket->compcomp_size_array[i];
                }
            }

            // We need to force a refresh to replace the uncompressed texture
            // This frees video memory and is also really required if we had
            // gone up a mipmap level
            extern ChartCanvas *cc1;
            if(cc1) {
                glChartCanvas::Invalidate(); // ensure we refresh
                cc1->Refresh();
            }
            ptd->compdata_ticks = 10;
        }

        if(bthread_debug)
            printf( "    Finished job: %08X  Jobs running: %d             Job count: %lu   \n",
                    ticket->ident, GetRunningJobCount(), (unsigned long)todo_list.GetCount());
    }

    //      Free all possible memory
    if(b_inCompressAllCharts) { // if compressing all write cache here
        ChartBase *pchart = ChartData->OpenChartFromDB(ticket->m_ChartPath, FULL_INIT );
        ChartData->DeleteCacheChart(pchart);
        delete ticket->pFact;
    }

    delete ticket;

    if(g_raster_format != GL_COMPRESSED_RGB_FXT1_3DFX) {
        running_list.DeleteObject(ticket);
        StartTopJob();
    }
}
예제 #2
0
bool glTextureManager::StartTopJob()
{
    wxJobListNode *node = todo_list.GetFirst();
    if(!node)
        return false;

    JobTicket *ticket = node->GetData();

    //  Is it possible to start another job?
    if(GetRunningJobCount() >= wxMax(m_max_jobs - ticket->b_throttle, 1))
        return false;

    todo_list.DeleteNode(node);

    glTextureDescriptor *ptd = ticket->pFact->GetpTD( ticket->rect );
    // don't need the job if we already have the compressed data
    if(ptd->comp_array[0]) {
        delete ticket;
        return StartTopJob();
    }

    if(ptd->map_array[0]) {
        if(ticket->level_min_request == 0) {
            // give level 0 buffer to the ticket
            ticket->level0_bits = ptd->map_array[0];
            ptd->map_array[0] = NULL;
        } else {
            // would be nicer to use reference counters
            int size = TextureTileSize(0, false);
            ticket->level0_bits = (unsigned char*)malloc(size);
            memcpy(ticket->level0_bits, ptd->map_array[0], size);
        }
    }

    running_list.Append(ticket);
    DoThreadJob(ticket);

    return true;
}
예제 #3
0
void glTextureManager::OnEvtThread( OCPN_CompressionThreadEvent & event )
{
    JobTicket *ticket = event.GetTicket();

    if(event.type ==1){
        if(m_progDialog){
            
            // Look for a matching entry...
            bool bfound = false;
            ProgressInfoItem *item;
            wxProgressInfoListNode *tnode = progList.GetFirst();
            while(tnode){
                item = tnode->GetData();
                if(item->file_path == ticket->m_ChartPath){
                    bfound = true;
                    break;
                }
                tnode = tnode->GetNext();
            }
            if(bfound){
                wxString msgx;
                if(1){
                    int bar_length = NBAR_LENGTH;
                    if(m_bcompact)
                        bar_length = 20;
                    
                    msgx += _T("\n[");
                    wxString block = wxString::Format(_T("%c"), 0x2589);
                    float cutoff = ((event.nstat+1) / (float)event.nstat_max) * bar_length;
                    for(int i=0 ; i < bar_length ; i++){
                        if(i <= cutoff)
                            msgx += block;
                        else
                            msgx += _T("-");
                    }
                    msgx += _T("]");

                    if(!m_bcompact){
                        wxString msgy;
                        msgy.Printf(_T("  [%3d/%3d]  "), event.nstat+1, event.nstat_max);
                        msgx += msgy;
                
                        wxFileName fn(ticket->m_ChartPath);
                        msgx += fn.GetFullName();
                    }
                }
                else
                    msgx.Printf(_T("\n %3d/%3d"), event.nstat+1, event.nstat_max);
                
                item->msgx = msgx;
            }

                // look for an empty slot
            else{
                bool bfound_empty = false;
                tnode = progList.GetFirst();
                while(tnode){
                    item = tnode->GetData();
                    if(item->file_path.IsEmpty()){
                        bfound_empty = true;
                        break;
                    }
                    
                    tnode = tnode->GetNext();
                }
                
                if(bfound_empty){
                    item->file_path = ticket->m_ChartPath;
                    wxString msgx;
                    msgx.Printf(_T("\n [%3d/%3d]"), event.nstat+1, event.nstat_max);
                    item->msgx = msgx;
                }
            }
        
            // Ready to compose
            wxString msg;
            tnode = progList.GetFirst();
            while(tnode){
                item = tnode->GetData();
                msg += item->msgx + _T("\n");
                tnode = tnode->GetNext();
            }
            
            if(m_skipout)
                m_progMsg = _T("Skipping, please wait...\n\n");
            
            m_progDialog->Update(m_jcnt, m_progMsg + msg, &m_skip );
            if(m_skip)
                m_skipout = true;
            return;
        }
    }
    
    if(ticket->b_isaborted || ticket->b_abort){
        for(int i=0 ; i < g_mipmap_max_level+1 ; i++) {
            free(ticket->comp_bits_array[i]);
            free( ticket->compcomp_bits_array[i] );
        }
        
        if(bthread_debug)
            printf( "    Abort job: %08X  Jobs running: %d             Job count: %lu   \n",
                    ticket->ident, GetRunningJobCount(), (unsigned long)todo_list.GetCount());
    } else if(!b_inCompressAllCharts) {
        //   Normal completion from here
        glTextureDescriptor *ptd = ticket->pFact->GetpTD( ticket->rect );
        if(ptd) {
            for(int i=0 ; i < g_mipmap_max_level+1 ; i++)
                ptd->comp_array[i] = ticket->comp_bits_array[i];

            if(ticket->bpost_zip_compress){
                for(int i=0 ; i < g_mipmap_max_level+1 ; i++){
                    ptd->compcomp_array[i] = ticket->compcomp_bits_array[i];
                    ptd->compcomp_size[i] = ticket->compcomp_size_array[i];
                }
            }

                    
                    
            // We need to force a refresh to replace the uncompressed texture
            // This frees video memory and is also really required if we had
            // gone up a mipmap level
            extern ChartCanvas *cc1;
            if(cc1) {
                glChartCanvas::Invalidate(); // ensure we refresh
                cc1->Refresh();
            }
            ptd->compdata_ticks = 10;
        }

        if(bthread_debug)
            printf( "    Finished job: %08X  Jobs running: %d             Job count: %lu   \n",
                    ticket->ident, GetRunningJobCount(), (unsigned long)todo_list.GetCount());
    }

    //      Free all possible memory
    if(b_inCompressAllCharts) { // if compressing all write cache here
        ChartBase *pchart = ChartData->OpenChartFromDB(ticket->m_ChartPath, FULL_INIT );
        ChartData->DeleteCacheChart(pchart);
        delete ticket->pFact;
    }

    wxProgressInfoListNode *tnode = progList.GetFirst();
    while(tnode){
        ProgressInfoItem *item = tnode->GetData();
        if(item->file_path == ticket->m_ChartPath)
            item->file_path = _T("");
        tnode = tnode->GetNext();
    }
    
    delete ticket;

    if(g_raster_format != GL_COMPRESSED_RGB_FXT1_3DFX) {
        running_list.DeleteObject(ticket);
        StartTopJob();
    }
}
예제 #4
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;
}
예제 #5
0
bool glTextureManager::DoThreadJob(JobTicket* pticket)
{
    if(bthread_debug)
        printf( "  Starting job: %08X  Jobs running: %d Jobs left: %lu\n", pticket->ident, GetRunningJobCount(), (unsigned long)todo_list.GetCount());
    
///    qDebug() << "Starting job" << GetRunningJobCount() <<  (unsigned long)todo_list.GetCount() << g_tex_mem_used;
    CompressionPoolThread *t = new CompressionPoolThread( pticket, this);
    pticket->pthread = t;
    
    t->Run();
    
    return true;
    
}