Exemplo n.º 1
0
void GetLevel0Map( glTextureDescriptor *ptd,  const wxRect &rect, wxString &chart_path )
{
    // Load level 0 uncompressed data
    wxRect ncrect(rect);
    ptd->map_array[0] = 0;
    
    ChartBase *pChart = ChartData->OpenChartFromDB( chart_path, FULL_INIT );
    if( !pChart ) {
        ptd->map_array[0] = (unsigned char *) calloc( ncrect.width * ncrect.height * 4, 1 );
        return;
    }
    
        //    Prime the pump with the "zero" level bits, ie. 1x native chart bits
    ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pChart );
        
    if( pBSBChart ) {
        unsigned char *t_buf = (unsigned char *) malloc( ncrect.width * ncrect.height * 4 );
        pBSBChart->GetChartBits( ncrect, t_buf, 1 );
        
        //    and cache them here
        ptd->map_array[0] = t_buf;
    } else {
        ptd->map_array[0] = (unsigned char *) calloc( ncrect.width * ncrect.height * 4, 1 );
        return;
    }
}
Exemplo n.º 2
0
bool JobTicket::DoJob()
{
    if(!rect.IsEmpty())
        return DoJob(rect);

    // otherwise this ticket covers all the rects in the chart
    ChartBase *pchart = ChartData->OpenChartFromDB( m_ChartPath, FULL_INIT );
    if(!pchart)
        return false;

    ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart );
    if(!pBSBChart)
        return false;

    int size_X = pBSBChart->GetSize_X();
    int size_Y = pBSBChart->GetSize_Y();

    int dim = g_GLOptions.m_iTextureDimension;
        
    int nx_tex = ceil( (float)size_X / dim );
    int ny_tex = ceil( (float)size_Y / dim );
        
    int nt = ny_tex * nx_tex;
        
    wxRect rect;
    rect.y = 0;
    rect.width = dim;
    rect.height = dim;
    for( int y = 0; y < ny_tex; y++ ) {
        
        if( pthread && pthread->m_pMessageTarget ) {
            OCPN_CompressionThreadEvent Nevent(wxEVT_OCPN_COMPRESSIONTHREAD, 0);
            Nevent.nstat = y;
            Nevent.nstat_max = ny_tex;
            Nevent.type = 1;
            Nevent.SetTicket(this);
            pthread->m_pMessageTarget->AddPendingEvent (Nevent);
        }
        
        rect.x = 0;
        for( int x = 0; x < nx_tex; x++ ) {
            if(!DoJob(rect))
                return false;
            
            pFact->UpdateCacheAllLevels(rect, global_color_scheme, compcomp_bits_array, compcomp_size_array);

            for(int i=0 ; i < g_mipmap_max_level+1 ; i++) {
                free(comp_bits_array[i]), comp_bits_array[i] = 0;
                free(compcomp_bits_array[i]), compcomp_bits_array[i] = 0;
            }

            
            rect.x += rect.width;
        }
        rect.y += rect.height;
    }
    
    return true;
}
Exemplo n.º 3
0
bool JobTicket::DoJob()
{
    if(!rect.IsEmpty())
        return DoJob(rect);

    // otherwise this ticket covers all the rects in the chart
    ChartBase *pchart = ChartData->OpenChartFromDB( m_ChartPath, FULL_INIT );
    if(!pchart)
        return false;

    ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart );
    if(!pBSBChart)
        return false;

    int size_X = pBSBChart->GetSize_X();
    int size_Y = pBSBChart->GetSize_Y();

    int dim = g_GLOptions.m_iTextureDimension;
        
    int nx_tex = ceil( (float)size_X / dim );
    int ny_tex = ceil( (float)size_Y / dim );
        
    int nt = ny_tex * nx_tex;
        
    wxRect rect;
    rect.y = 0;
    rect.width = dim;
    rect.height = dim;
    for( int y = 0; y < ny_tex; y++ ) {
        rect.x = 0;
        for( int x = 0; x < nx_tex; x++ ) {
            if(!DoJob(rect))
                return false;
            
            pFact->UpdateCacheAllLevels(rect, global_color_scheme, compcomp_bits_array, compcomp_size_array);

            for(int i=0 ; i < g_mipmap_max_level+1 ; i++) {
                free(comp_bits_array[i]), comp_bits_array[i] = 0;
                free(compcomp_bits_array[i]), compcomp_bits_array[i] = 0;
            }

            
            rect.x += rect.width;
        }
        rect.y += rect.height;
    }
    return true;
}
Exemplo n.º 4
0
bool JobTicket::DoJob(const wxRect &rect)
{
    unsigned char *bit_array[10];
    for(int i=0 ; i < 10 ; i++)
        bit_array[i] = 0;

    wxRect ncrect(rect);

    bit_array[0] = level0_bits;
    level0_bits = NULL;

    if(!bit_array[0]) {
        //  Grab a copy of the level0 chart bits
        // we could alternately subsample grabbing leveln chart bits
        // directly here to speed things up...
        ChartBase *pchart;
        int index;
    
        if(ChartData){
            index =  ChartData->FinddbIndex( m_ChartPath );
            pchart = ChartData->OpenChartFromDBAndLock(index, FULL_INIT );

            if(pchart && ChartData->IsChartLocked( index )){
                ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart );
                if( pBSBChart ) {
                    bit_array[0] = (unsigned char *) malloc( ncrect.width * ncrect.height * 4 );
                    pBSBChart->GetChartBits( ncrect, bit_array[0], 1 );
                }
                ChartData->UnLockCacheChart(index);
            }
            else
                bit_array[0] = NULL;
        }
    }
    
    //OK, got the bits?
    int ssize, dim;
    if(!bit_array[0] )
        return false;
    
    //  Fill in the rest of the private uncompressed array
    dim = g_GLOptions.m_iTextureDimension;
    dim /= 2;
    for( int i = 1 ; i < g_mipmap_max_level+1 ; i++ ){
        size_t nmalloc = wxMax(dim * dim * 3, 4*4*3);
        bit_array[i] = (unsigned char *) malloc( nmalloc );
        MipMap_24( 2*dim, 2*dim, bit_array[i - 1], bit_array[i] );
        dim /= 2;
    }
        
    int texture_level = 0;
    for( int level = level_min_request; level < g_mipmap_max_level+1 ; level++ ){
        int dim = TextureDim(level);
        int size = TextureTileSize(level, true);
        unsigned char *tex_data = (unsigned char*)malloc(size);
        if(g_raster_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) {
            // color range fit is worse quality but twice as fast
            int flags = squish::kDxt1 | squish::kColourRangeFit;
            
            if( g_GLOptions.m_bTextureCompressionCaching) {
                /* use slower cluster fit since we are building the cache for
                 * better quality, this takes roughly 25% longer and uses about
                 * 10% more disk space (result doesn't compress as well with lz4) */
                flags = squish::kDxt1 | squish::kColourClusterFit;
            }
            
            OCPNStopWatch sww;
            squish::CompressImageRGBpow2_Flatten_Throttle_Abort( bit_array[level], dim, dim, tex_data, flags,
                                                                 true, b_throttle ? throttle_func : 0, &sww, b_abort );
            
        } else if(g_raster_format == GL_ETC1_RGB8_OES) 
            CompressDataETC(bit_array[level], dim, size, tex_data, b_abort);
        else if(g_raster_format == GL_COMPRESSED_RGB_FXT1_3DFX) {
            if(!CompressUsingGPU(bit_array[level], dim, size, tex_data, texture_level, binplace)) {
                b_abort = true;
                break;
            }

            if(binplace)
                g_tex_mem_used += size;

            texture_level++;
        }
        comp_bits_array[level] = tex_data;
            
        if(b_abort){
            for( int i = 0; i < g_mipmap_max_level+1; i++ ){
                free( bit_array[i] );
                bit_array[i] = 0;
            }
            return false;
        }
    }
        
    //  All done with the uncompressed data in the thread
    for( int i = 0; i < g_mipmap_max_level+1; i++ ) {
        free( bit_array[i] );
        bit_array[i] = 0;
    }

    if(b_throttle)
        wxThread::Sleep(1);
    
    if(b_abort)
        return false;

    if(bpost_zip_compress) {
            
        int max_compressed_size = LZ4_COMPRESSBOUND(g_tile_size);
        for(int level = level_min_request; level < g_mipmap_max_level+1 ; level++){
            if(b_abort)
                return false;

            unsigned char *compressed_data = (unsigned char *)malloc(max_compressed_size);
            int csize = TextureTileSize(level, true);

            char *src = (char *)comp_bits_array[level];
            int compressed_size = LZ4_compressHC2( src, (char *)compressed_data, csize, 4);
            // shrink buffer to actual size.
            // This will greatly reduce ram usage, ratio usually 10:1
            // there might be a more efficient way than realloc...
            compressed_data = (unsigned char*)realloc(compressed_data, compressed_size);
            compcomp_bits_array[level] = compressed_data;
            compcomp_size_array[level] = compressed_size;
        }
    }

    return true;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}