예제 #1
0
   void* crnlib_malloc(size_t size, size_t* pActual_size)
   {
      size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);
      if (!size)
         size = sizeof(uint32);

      if (size > CRNLIB_MAX_POSSIBLE_BLOCK_SIZE)
      {
         crnlib_mem_error("crnlib_malloc: size too big");
         return NULL;
      }

      size_t actual_size = size;
      uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));

      if (pActual_size)
         *pActual_size = actual_size;

      if ((!p_new) || (actual_size < size))
      {
         crnlib_mem_error("crnlib_malloc: out of memory");
         return NULL;
      }

      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0);

#if CRNLIB_MEM_STATS
      CRNLIB_ASSERT((*g_pMSize)(p_new, g_pUser_data) == actual_size);
      update_total_allocated(1, static_cast<mem_stat_t>(actual_size));
#endif

      return p_new;
   }
예제 #2
0
   bool task_pool::init(uint num_threads)
   {
      CRNLIB_ASSERT(num_threads <= cMaxThreads);
      num_threads = math::minimum<uint>(num_threads, cMaxThreads);

      deinit();

      m_task_condition_var.lock();

      m_num_threads = num_threads;

      bool succeeded = true;
      for (uint i = 0; i < num_threads; i++)
      {
         m_threads[i] = (HANDLE)_beginthreadex(NULL, 32768, thread_func, this, 0, NULL);

         CRNLIB_ASSERT(m_threads[i] != 0);
         if (!m_threads[i])
         {
            succeeded = false;
            break;
         }
      }

      m_task_condition_var.unlock();

      if (!succeeded)
      {
         deinit();
         return false;
      }
      return true;
   }
예제 #3
0
   static mem_stat_t update_total_allocated(int block_delta, mem_stat_t byte_delta)
   {
      mem_stat_t cur_total_blocks;
      for ( ; ; )
      {
         cur_total_blocks = (mem_stat_t)g_total_blocks;
         mem_stat_t new_total_blocks = static_cast<mem_stat_t>(cur_total_blocks + block_delta);
         CRNLIB_ASSERT(new_total_blocks >= 0);
         if (CRNLIB_MEM_COMPARE_EXCHANGE(&g_total_blocks, new_total_blocks, cur_total_blocks) == cur_total_blocks)
            break;
      }

      mem_stat_t cur_total_allocated, new_total_allocated;
      for ( ; ; )
      {
         cur_total_allocated = g_total_allocated;
         new_total_allocated = static_cast<mem_stat_t>(cur_total_allocated + byte_delta);
         CRNLIB_ASSERT(new_total_allocated >= 0);
         if (CRNLIB_MEM_COMPARE_EXCHANGE(&g_total_allocated, new_total_allocated, cur_total_allocated) == cur_total_allocated)
            break;
      }
      for ( ; ; )
      {
         mem_stat_t cur_max_allocated = g_max_allocated;
         mem_stat_t new_max_allocated = CRNLIB_MAX(new_total_allocated, cur_max_allocated);
         if (CRNLIB_MEM_COMPARE_EXCHANGE(&g_max_allocated, new_max_allocated, cur_max_allocated) == cur_max_allocated)
            break;
      }
      return new_total_allocated;
   }
예제 #4
0
   static void* crnlib_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data)
   {
      pUser_data;

      void* p_new;

      if (!p)
      {
         p_new = ::malloc(size);
         CRNLIB_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0 );

         if (pActual_size)
            *pActual_size = p_new ? ::_msize(p_new) : 0;
      }
      else if (!size)
      {
         ::free(p);
         p_new = NULL;

         if (pActual_size)
            *pActual_size = 0;
      }
      else
      {
         void* p_final_block = p;
#ifdef WIN32
         p_new = ::_expand(p, size);
#else

         p_new = NULL;
#endif

         if (p_new)
         {
            CRNLIB_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
            p_final_block = p_new;
         }
         else if (movable)
         {
            p_new = ::realloc(p, size);

            if (p_new)
            {
               CRNLIB_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
               p_final_block = p_new;
            }
         }

         if (pActual_size)
            *pActual_size = ::_msize(p_final_block);
      }

      return p_new;
   }
예제 #5
0
   bool task_pool::init(uint num_threads)
   {
      CRNLIB_ASSERT(num_threads <= cMaxThreads);
      num_threads = math::minimum<uint>(num_threads, cMaxThreads);

      deinit();

      bool succeeded = true;

      m_num_threads = 0;
      while (m_num_threads < num_threads)
      {
         int status = pthread_create(&m_threads[m_num_threads], NULL, thread_func, this);
         if (status)
         {
            succeeded = false;
            break;
         }

         m_num_threads++;
      }

      if (!succeeded)
      {
         deinit();
         return false;
      }

      return true;
   }
예제 #6
0
   void task_pool::join()
   {
      for ( ; ; )
      {
         m_task_condition_var.lock();

         if (!m_tasks.empty())
         {
            task tsk(m_tasks.front());
            m_tasks.pop_front();

            m_task_condition_var.unlock();

            process_task(tsk);
         }
         else
         {
            int result = m_task_condition_var.wait(join_condition_func, this);
            result;
            CRNLIB_ASSERT(result >= 0);

            m_task_condition_var.unlock();

            break;
         }
      }
   }
   const wchar_t* texture_file_types::get_extension(format fmt)
   {
      CRNLIB_ASSERT(fmt < cNumFileFormats);
      if (fmt >= cNumFileFormats)
         return NULL;

      static const wchar_t* extensions[cNumFileFormats] =
      {
         L"tga",
         L"png",
         L"jpg",
         L"jpeg",
         L"bmp",
         L"gif",
         L"tif",
         L"tiff",
         L"ppm",
         L"pgm",
         L"dds",
         L"psd",
         L"jp2",
         L"crn",
         L"<clipboard>",
         L"<dragdrop>"
      };
      return extensions[fmt];
   }
예제 #8
0
   void semaphore::release(long releaseCount)
   {
      CRNLIB_ASSERT(releaseCount >= 1);

      int status = 0;
#ifdef WIN32
      if (1 == releaseCount)
         status = sem_post(&m_sem);
      else
         status = sem_post_multiple(&m_sem, releaseCount);
#else
      while (releaseCount > 0)
      {
         status = sem_post(&m_sem);
         if (status)
            break;
         releaseCount--;
      }
#endif

      if (status)
      {
         CRNLIB_FAIL("semaphore: sem_post() or sem_post_multiple() failed");
      }
   }
예제 #9
0
   void* crnlib_realloc(void* p, size_t size, size_t* pActual_size, bool movable)
   {
      if ((ptr_bits_t)p & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1))
      {
         crnlib_mem_error("crnlib_realloc: bad ptr");
         return NULL;
      }

      if (size > CRNLIB_MAX_POSSIBLE_BLOCK_SIZE)
      {
         crnlib_mem_error("crnlib_malloc: size too big");
         return NULL;
      }

#if CRNLIB_MEM_STATS
      size_t cur_size = p ? (*g_pMSize)(p, g_pUser_data) : 0;
      CRNLIB_ASSERT(!p || (cur_size >= sizeof(uint32)));
#endif
      if ((size) && (size < sizeof(uint32))) 
         size = sizeof(uint32);

      size_t actual_size = size;
      void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);

      if (pActual_size)
         *pActual_size = actual_size;

      CRNLIB_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1)) == 0);

#if CRNLIB_MEM_STATS
      CRNLIB_ASSERT(!p_new || ((*g_pMSize)(p_new, g_pUser_data) == actual_size));

      int num_new_blocks = 0;
      if (p)
      {
         if (!p_new)
            num_new_blocks = -1;
      }
      else if (p_new)
      {
         num_new_blocks = 1;
      }
      update_total_allocated(num_new_blocks, static_cast<mem_stat_t>(actual_size) - static_cast<mem_stat_t>(cur_size));
#endif

      return p_new;
   }
 void timer::stop()
 {
    CRNLIB_ASSERT(m_started);
                
    QueryPerformanceCounter((LARGE_INTEGER*)&m_stop_time);
    
    m_stopped = true;
 }
예제 #11
0
 semaphore::semaphore(long initialCount, long maximumCount, const char* pName)
 {
    maximumCount, pName;
    CRNLIB_ASSERT(maximumCount >= initialCount);
    if (sem_init(&m_sem, 0, initialCount))
    {
       CRNLIB_FAIL("semaphore: sem_init() failed");
    }
 }
   bool command_line_params::is_param(uint index) const
   {
      CRNLIB_ASSERT(index < m_params.size());
      if (index >= m_params.size())
         return false;

      const dynamic_wstring& w = m_params[index];
      if (w.is_empty())
         return false;

      return (w.get_len() >= 2) && ((w[0] == L'-') || (w[0] == L'/'));
   }
예제 #13
0
   bool task_pool::queue_task(task_callback_func pFunc, uint64 data, void* pData_ptr)
   {
      CRNLIB_ASSERT(m_num_threads);
      CRNLIB_ASSERT(pFunc);

      task tsk;
      tsk.m_callback = pFunc;
      tsk.m_data = data;
      tsk.m_pData_ptr = pData_ptr;
      tsk.m_flags = 0;

      atomic_increment32(&m_total_submitted_tasks);
      if (!m_task_stack.try_push(tsk))
      {
         atomic_increment32(&m_total_completed_tasks);
         return false;
      }

      m_tasks_available.release(1);

      return true;
   }
 uint64 timer::get_elapsed_us() const
 {
    CRNLIB_ASSERT(m_started);
    if (!m_started)
       return 0;
       
    uint64 stop_time = m_stop_time;
    if (!m_stopped)
       QueryPerformanceCounter((LARGE_INTEGER*)&stop_time);
    
    uint64 delta = stop_time - m_start_time;
    return (delta * 1000000ULL + (g_freq >> 1U)) / g_freq;      
 }
예제 #15
0
   // It's the object's responsibility to delete pObj within the execute_task() method, if needed!
   bool task_pool::queue_task(executable_task* pObj, uint64 data, void* pData_ptr)
   {
      CRNLIB_ASSERT(m_num_threads);
      CRNLIB_ASSERT(pObj);

      task tsk;
      tsk.m_pObj = pObj;
      tsk.m_data = data;
      tsk.m_pData_ptr = pData_ptr;
      tsk.m_flags = cTaskFlagObject;

      atomic_increment32(&m_total_submitted_tasks);
      if (!m_task_stack.try_push(tsk))
      {
         atomic_increment32(&m_total_completed_tasks);
         return false;
      }

      m_tasks_available.release(1);

      return true;
   }
 double timer::get_elapsed_secs() const
 {
    CRNLIB_ASSERT(m_started);
    if (!m_started)
       return 0;
    
    uint64 stop_time = m_stop_time;
    if (!m_stopped)
       QueryPerformanceCounter((LARGE_INTEGER*)&stop_time);
       
    uint64 delta = stop_time - m_start_time;
    return delta * g_inv_freq;
 }
static bool create_dds_tex(const crn_comp_params &params, dds_texture &dds_tex)
{
    image_u8 images[cCRNMaxFaces][cCRNMaxLevels];

    bool has_alpha = false;
    for (uint face_index = 0; face_index < params.m_faces; face_index++)
    {
        for (uint level_index = 0; level_index < params.m_levels; level_index++)
        {
            const uint width = math::maximum(1U, params.m_width >> level_index);
            const uint height = math::maximum(1U, params.m_height >> level_index);

            if (!params.m_pImages[face_index][level_index])
                return false;

            images[face_index][level_index].alias((color_quad_u8*)params.m_pImages[face_index][level_index], width, height);
            if (!has_alpha)
                has_alpha = image_utils::has_alpha(images[face_index][level_index]);
        }
    }

    for (uint face_index = 0; face_index < params.m_faces; face_index++)
        for (uint level_index = 0; level_index < params.m_levels; level_index++)
            images[face_index][level_index].set_component_valid(3, has_alpha);

    face_vec faces(params.m_faces);

    for (uint face_index = 0; face_index < params.m_faces; face_index++)
    {
        for (uint level_index = 0; level_index < params.m_levels; level_index++)
        {
            mip_level *pMip = crnlib_new<mip_level>();

            image_u8 *pImage = crnlib_new<image_u8>();
            pImage->swap(images[face_index][level_index]);
            pMip->assign(pImage);

            faces[face_index].push_back(pMip);
        }
    }

    dds_tex.assign(faces);

#ifdef CRNLIB_BUILD_DEBUG
    CRNLIB_ASSERT(dds_tex.check());
#endif

    return true;
}
   bool command_line_params::parse(const wchar_t* pCmd_line, uint n, const param_desc* pParam_desc, bool skip_first_param)
   {
      CRNLIB_ASSERT(n && pParam_desc);
   
      dynamic_wstring_array p;
      if (!split_params(pCmd_line, p))
         return 0;

      if (p.empty())
         return 0;

      if (skip_first_param)
         p.erase(0U);

      return parse(p, n, pParam_desc);
   }
   bool command_line_params::is_param(uint index) const
   {
      CRNLIB_ASSERT(index < m_params.size());
      if (index >= m_params.size())
         return false;

      const dynamic_string& w = m_params[index];
      if (w.is_empty())
         return false;

#if CRNLIB_CMD_LINE_ALLOW_SLASH_PARAMS
      return (w.get_len() >= 2) && ((w[0] == '-') || (w[0] == '/'));
#else
      return (w.get_len() >= 2) && (w[0] == '-');
#endif
   }
   const wchar_t* get_texture_type_desc(texture_type t)
   {
      switch (t)
      {
         case cTextureTypeUnknown:                 return L"Unknown";
         case cTextureTypeRegularMap:              return L"2D map";
         case cTextureTypeNormalMap:               return L"Normal map";
         case cTextureTypeVerticalCrossCubemap:    return L"Vertical Cross Cubemap";
         case cTextureTypeCubemap:                 return L"Cubemap";
         default: break;
      }

      CRNLIB_ASSERT(false);

      return L"?";
   }
예제 #21
0
   // It's the object's responsibility to crnlib_delete pObj within the execute_task() method, if needed!
   void task_pool::queue_task(executable_task* pObj, uint64 data, void* pData_ptr)
   {
      CRNLIB_ASSERT(pObj);

      m_task_condition_var.lock();

      task tsk;
      tsk.m_pObj = pObj;
      tsk.m_data = data;
      tsk.m_pData_ptr = pData_ptr;
      tsk.m_flags = cTaskFlagObject;
      m_tasks.push_back(tsk);

      m_num_outstanding_tasks++;

      m_task_condition_var.unlock();
   }
예제 #22
0
   void semaphore::try_release(long releaseCount)
   {
      CRNLIB_ASSERT(releaseCount >= 1);

#ifdef WIN32
      if (1 == releaseCount)
         sem_post(&m_sem);
      else
         sem_post_multiple(&m_sem, releaseCount);
#else
      while (releaseCount > 0)
      {
         sem_post(&m_sem);
         releaseCount--;
      }
#endif
   }
예제 #23
0
   void task_pool::queue_task(task_callback_func pFunc, uint64 data, void* pData_ptr)
   {
      CRNLIB_ASSERT(pFunc);

      m_task_condition_var.lock();

      task tsk;
      tsk.m_callback = pFunc;
      tsk.m_data = data;
      tsk.m_pData_ptr = pData_ptr;
      tsk.m_flags = 0;
      m_tasks.push_back(tsk);

      m_num_outstanding_tasks++;

      m_task_condition_var.unlock();
   }
예제 #24
0
   void crnlib_free(void* p)
   {
      if (!p)
         return;

      if (reinterpret_cast<ptr_bits_t>(p) & (CRNLIB_MIN_ALLOC_ALIGNMENT - 1))
      {
         crnlib_mem_error("crnlib_free: bad ptr");
         return;
      }

#if CRNLIB_MEM_STATS
      size_t cur_size = (*g_pMSize)(p, g_pUser_data);
      CRNLIB_ASSERT(cur_size >= sizeof(uint32));
      update_total_allocated(-1, -static_cast<mem_stat_t>(cur_size));
#endif

      (*g_pRealloc)(p, 0, NULL, true, g_pUser_data);
   }
   uint command_line_params::find(uint num_keys, const wchar_t** ppKeys, crnlib::vector<param_map_const_iterator>* pIterators, crnlib::vector<uint>* pUnmatched_indices) const
   {
      CRNLIB_ASSERT(ppKeys);
      
      if (pUnmatched_indices)
      {
         pUnmatched_indices->resize(m_params.size());
         for (uint i = 0; i < m_params.size(); i++)
            (*pUnmatched_indices)[i] = i;
      }
      
      uint n = 0;
      for (uint i = 0; i < num_keys; i++)
      {
         const wchar_t* pKey = ppKeys[i];

         param_map_const_iterator begin, end;
         find(pKey, begin, end);
         
         while (begin != end)
         {
            if (pIterators)   
               pIterators->push_back(begin);
            
            if (pUnmatched_indices)
            {
               int k = pUnmatched_indices->find(begin->second.m_index);
               if (k >= 0)
                  pUnmatched_indices->erase_unordered(k);
            }
               
            n++;
            begin++;
         }
      }
   
      return n;
   }
예제 #26
0
   unsigned __stdcall task_pool::thread_func(void* pContext)
   {
      //set_thread_name(GetCurrentThreadId(), "taskpoolhelper");

      task_pool* pPool = static_cast<task_pool*>(pContext);

      for ( ; ; )
      {
         pPool->m_task_condition_var.lock();

         int result = pPool->m_task_condition_var.wait(wait_condition_func, pPool);

         CRNLIB_ASSERT(result >= 0);

         if ((result < 0) || (pPool->m_exit_flag))
         {
            pPool->m_task_condition_var.unlock();
            break;
         }

         if (pPool->m_tasks.empty())
            pPool->m_task_condition_var.unlock();
         else
         {
            task tsk(pPool->m_tasks.front());
            pPool->m_tasks.pop_front();

            pPool->m_task_condition_var.unlock();

            pPool->process_task(tsk);
         }
      }

      _endthreadex(0);
      return 0;
   }
예제 #27
0
   bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
   {
      if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms))
         return false;
                  
      huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);;
            
      uint max_freq = 0;
      uint total_freq = 0;
      
      uint num_used_syms = 0;
      for (uint i = 0; i < num_syms; i++)
      {
         uint freq = pFreq[i];
         
         if (!freq)
            pCodesizes[i] = 0;
         else
         {
            total_freq += freq;
            max_freq = math::maximum(max_freq, freq);
            
            sym_freq& sf = state.syms0[num_used_syms];
            sf.m_left = (uint16)i;
            sf.m_right = cUINT16_MAX;
            sf.m_freq = freq;
            num_used_syms++;
         }            
      }
      
      total_freq_ret = total_freq;

      if (num_used_syms == 1)
      {
         pCodesizes[state.syms0[0].m_left] = 1;
         return true;
      }

      sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);

#if USE_CALCULATE_MINIMUM_REDUNDANCY
      int x[cHuffmanMaxSupportedSyms];
      for (uint i = 0; i < num_used_syms; i++)
         x[i] = state.syms0[i].m_freq;
      
      calculate_minimum_redundancy(x, num_used_syms);
      
      uint max_len = 0;
      for (uint i = 0; i < num_used_syms; i++)
      {
         uint len = x[i];
         max_len = math::maximum(len, max_len);
         pCodesizes[state.syms0[i].m_left] = static_cast<uint8>(len);
      }
      
      return true;
#else    
      // Dummy node
      sym_freq& sf = state.syms0[num_used_syms];
      sf.m_left = cUINT16_MAX;
      sf.m_right = cUINT16_MAX;
      sf.m_freq = UINT_MAX;
      
      uint next_internal_node = num_used_syms + 1;
            
      uint queue_front = 0;
      uint queue_end = 0;
            
      uint next_lowest_sym = 0;
      
      uint num_nodes_remaining = num_used_syms;
      do
      {
         uint left_freq = syms[next_lowest_sym].m_freq;
         uint left_child = next_lowest_sym;
         
         if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < left_freq))
         {
            left_child = state.queue[queue_front];
            left_freq = syms[left_child].m_freq;
            
            queue_front++;
         }
         else
            next_lowest_sym++;
         
         uint right_freq = syms[next_lowest_sym].m_freq;
         uint right_child = next_lowest_sym;

         if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < right_freq))
         {
            right_child = state.queue[queue_front];
            right_freq = syms[right_child].m_freq;
            
            queue_front++;
         }
         else
            next_lowest_sym++;
                        
         const uint internal_node_index = next_internal_node;
         next_internal_node++;

         CRNLIB_ASSERT(next_internal_node < CRNLIB_ARRAYSIZE(state.syms0));
         
         syms[internal_node_index].m_freq = left_freq + right_freq;
         syms[internal_node_index].m_left = static_cast<uint16>(left_child);
         syms[internal_node_index].m_right = static_cast<uint16>(right_child);
         
         CRNLIB_ASSERT(queue_end < huffman_work_tables::cMaxInternalNodes);
         state.queue[queue_end] = static_cast<uint16>(internal_node_index);
         queue_end++;
                  
         num_nodes_remaining--;
         
      } while (num_nodes_remaining > 1);
      
      CRNLIB_ASSERT(next_lowest_sym == num_used_syms);
      CRNLIB_ASSERT((queue_end - queue_front) == 1);
      
      uint cur_node_index = state.queue[queue_front];
      
      uint32* pStack = (syms == state.syms0) ? (uint32*)state.syms1 : (uint32*)state.syms0;
      uint32* pStack_top = pStack;

      uint max_level = 0;
      
      for ( ; ; ) 
      {
         uint level = cur_node_index >> 16;
         uint node_index = cur_node_index & 0xFFFF;
         
         uint left_child = syms[node_index].m_left;
         uint right_child = syms[node_index].m_right;
         
         uint next_level = (cur_node_index + 0x10000) & 0xFFFF0000;
                           
         if (left_child < num_used_syms)
         {
            max_level = math::maximum(max_level, level);
            
            pCodesizes[syms[left_child].m_left] = static_cast<uint8>(level + 1);
            
            if (right_child < num_used_syms)
            {
               pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
               
               if (pStack == pStack_top) break;
               cur_node_index = *--pStack;
            }
            else
            {
               cur_node_index = next_level | right_child;
            }
         }
         else
         {
            if (right_child < num_used_syms)
            {
               max_level = math::maximum(max_level, level);
               
               pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
                              
               cur_node_index = next_level | left_child;
            }
            else
            {
               *pStack++ = next_level | left_child;
                              
               cur_node_index = next_level | right_child;
            }
         }
      }
      
      max_code_size = max_level + 1;
#endif
                  
      return true;
   }
   bool command_line_params::parse(const dynamic_wstring_array& params, uint n, const param_desc* pParam_desc)
   {
      CRNLIB_ASSERT(n && pParam_desc);
      
      m_params = params;
      
      uint arg_index = 0;
      while (arg_index < params.size())
      {
         const uint cur_arg_index = arg_index;
         const dynamic_wstring& src_param = params[arg_index++];
               
         if (src_param.is_empty())
            continue;
                           
         if ((src_param[0] == L'/') || (src_param[0] == L'-'))
         {
            if (src_param.get_len() < 2)
            {
               console::error(L"Invalid command line parameter: \"%s\"", src_param.get_ptr());
               return false;
            }
            
            dynamic_wstring key_str(src_param);
            
            key_str.right(1);
            
            int modifier = 0;
            wchar_t c = key_str[key_str.get_len() - 1];
            if (c == L'+')
               modifier = 1;
            else if (c == L'-') 
               modifier = -1;
               
            if (modifier)
               key_str.left(key_str.get_len() - 1);
                        
            uint param_index;
            for (param_index = 0; param_index < n; param_index++)
               if (key_str == pParam_desc[param_index].m_pName)
                  break;
                  
            if (param_index == n)
            {
               console::error(L"Unrecognized command line parameter: \"%s\"", src_param.get_ptr());
               return false;  
            }
            
            const param_desc& desc = pParam_desc[param_index];
            
            const uint cMaxValues = 16;
            dynamic_wstring val_str[cMaxValues];
            uint num_val_strs = 0;
            if (desc.m_num_values) 
            {  
               CRNLIB_ASSERT(desc.m_num_values <= cMaxValues);
               
               if ((arg_index + desc.m_num_values) > params.size())
               {
                  console::error(L"Expected %u value(s) after command line parameter: \"%s\"", desc.m_num_values, src_param.get_ptr());
                  return false;  
               }
               
               for (uint v = 0; v < desc.m_num_values; v++)
                  val_str[num_val_strs++] = params[arg_index++];
            }             
            
            dynamic_wstring_array strings;
            
            if ((desc.m_support_listing_file) && (val_str[0].get_len() >= 2) && (val_str[0][0] == L'@'))
            {
               dynamic_wstring filename(val_str[0]);
               filename.right(1);
               filename.unquote();
            
               if (!load_string_file(filename.get_ptr(), strings))
               {
                  console::error(L"Failed loading listing file \"%s\"!", filename.get_ptr());
                  return false;
               }
            }
            else
            {
               for (uint v = 0; v < num_val_strs; v++)
               {
                  val_str[v].unquote();
                  strings.push_back(val_str[v]);
               }
            }
            
            param_value pv;
            pv.m_values.swap(strings);
            pv.m_index = cur_arg_index;
            pv.m_modifier = (int8)modifier;
            m_param_map.insert(std::make_pair(key_str, pv));
         }
         else
         {
            param_value pv;
            pv.m_values.push_back(src_param);
            pv.m_values.back().unquote();
            pv.m_index = cur_arg_index;
            m_param_map.insert(std::make_pair(g_empty_dynamic_wstring, pv));
         }
      }

      return true;
   }
예제 #29
0
   bool elemental_vector::increase_capacity(uint min_new_capacity, bool grow_hint, uint element_size, object_mover pMover, bool nofail)
   {
      CRNLIB_ASSERT(m_size <= m_capacity);
#ifdef CRNLIB_PLATFORM_PC_X64
      CRNLIB_ASSERT(min_new_capacity < (0x400000000ULL / element_size));
#else
      CRNLIB_ASSERT(min_new_capacity < (0x7FFF0000U / element_size));
#endif

      if (m_capacity >= min_new_capacity)
         return true;

      size_t new_capacity = min_new_capacity;
      if ((grow_hint) && (!math::is_power_of_2(new_capacity)))
         new_capacity = math::next_pow2(new_capacity);

      CRNLIB_ASSERT(new_capacity && (new_capacity > m_capacity));

      const size_t desired_size = element_size * new_capacity;
      size_t actual_size;
      if (!pMover)
      {
         void* new_p = crnlib_realloc(m_p, desired_size, &actual_size, true);
         if (!new_p)
         {
            if (nofail)
               return false;

            char buf[256];
#ifdef _MSC_VER
            sprintf_s(buf, sizeof(buf), "vector: crnlib_realloc() failed allocating %u bytes", (uint)desired_size);
#else
            sprintf(buf, "vector: crnlib_realloc() failed allocating %u bytes", (uint)desired_size);
#endif
            CRNLIB_FAIL(buf);
         }
         m_p = new_p;
      }
      else
      {
         void* new_p = crnlib_malloc(desired_size, &actual_size);
         if (!new_p)
         {
            if (nofail)
               return false;

            char buf[256];
#ifdef _MSC_VER
            sprintf_s(buf, sizeof(buf), "vector: crnlib_malloc() failed allocating %u bytes", (uint)desired_size);
#else
            sprintf(buf, "vector: crnlib_malloc() failed allocating %u bytes", (uint)desired_size);
#endif
            CRNLIB_FAIL(buf);
         }

         (*pMover)(new_p, m_p, m_size);

         if (m_p)
            crnlib_free(m_p);

         m_p = new_p;
      }

      if (actual_size > desired_size)
         m_capacity = static_cast<uint>(actual_size / element_size);
      else
         m_capacity = static_cast<uint>(new_capacity);

      return true;
   }
bool create_texture_mipmaps(dds_texture &work_tex, const crn_comp_params &params, const crn_mipmap_params &mipmap_params, bool generate_mipmaps)
{
    crn_comp_params new_params(params);

    bool generate_new_mips = false;

    switch (mipmap_params.m_mode)
    {
    case cCRNMipModeUseSourceOrGenerateMips:
    {
        if (work_tex.get_num_levels() == 1)
            generate_new_mips = true;
        break;
    }
    case cCRNMipModeUseSourceMips:
    {
        break;
    }
    case cCRNMipModeGenerateMips:
    {
        generate_new_mips = true;
        break;
    }
    case cCRNMipModeNoMips:
    {
        work_tex.discard_mipmaps();
        break;
    }
    default:
    {
        CRNLIB_ASSERT(0);
        break;
    }
    }

    rect window_rect(mipmap_params.m_window_left, mipmap_params.m_window_top, mipmap_params.m_window_right, mipmap_params.m_window_bottom);

    if (!window_rect.is_empty())
    {
        if (work_tex.get_num_faces() > 1)
        {
            console::warning(L"Can't crop cubemap textures");
        }
        else
        {
            console::info(L"Cropping input texture from window (%ux%u)-(%ux%u)", window_rect.get_left(), window_rect.get_top(), window_rect.get_right(), window_rect.get_bottom());

            if (!work_tex.crop(window_rect.get_left(), window_rect.get_top(), window_rect.get_width(), window_rect.get_height()))
                console::warning(L"Failed cropping window rect");
        }
    }

    int new_width = work_tex.get_width();
    int new_height = work_tex.get_height();

    if ((mipmap_params.m_clamp_width) && (mipmap_params.m_clamp_height))
    {
        if ((new_width > (int)mipmap_params.m_clamp_width) || (new_height > (int)mipmap_params.m_clamp_height))
        {
            if (!mipmap_params.m_clamp_scale)
            {
                if (work_tex.get_num_faces() > 1)
                {
                    console::warning(L"Can't crop cubemap textures");
                }
                else
                {
                    new_width = math::minimum<uint>(mipmap_params.m_clamp_width, new_width);
                    new_height = math::minimum<uint>(mipmap_params.m_clamp_height, new_height);
                    console::info(L"Clamping input texture to %ux%u", new_width, new_height);
                    work_tex.crop(0, 0, new_width, new_height);
                }
            }
        }
    }

    if (mipmap_params.m_scale_mode != cCRNSMDisabled)
    {
        bool is_pow2 = math::is_power_of_2((uint32)new_width) && math::is_power_of_2((uint32)new_height);

        switch (mipmap_params.m_scale_mode)
        {
        case cCRNSMAbsolute:
        {
            new_width = (uint)mipmap_params.m_scale_x;
            new_height = (uint)mipmap_params.m_scale_y;
            break;
        }
        case cCRNSMRelative:
        {
            new_width = (uint)(mipmap_params.m_scale_x * new_width + .5f);
            new_height = (uint)(mipmap_params.m_scale_y * new_height + .5f);
            break;
        }
        case cCRNSMLowerPow2:
        {
            if (!is_pow2)
                math::compute_lower_pow2_dim(new_width, new_height);
            break;
        }
        case cCRNSMNearestPow2:
        {
            if (!is_pow2)
            {
                int lwidth = new_width;
                int lheight = new_height;
                math::compute_lower_pow2_dim(lwidth, lheight);

                int uwidth = new_width;
                int uheight = new_height;
                math::compute_upper_pow2_dim(uwidth, uheight);

                if (labs(new_width - lwidth) < labs(new_width - uwidth))
                    new_width = lwidth;
                else
                    new_width = uwidth;

                if (labs(new_height - lheight) < labs(new_height - uheight))
                    new_height = lheight;
                else
                    new_height = uheight;
            }
            break;
        }
        case cCRNSMNextPow2:
        {
            if (!is_pow2)
                math::compute_upper_pow2_dim(new_width, new_height);
            break;
        }
        default:
            break;
        }
    }

    if ((mipmap_params.m_clamp_width) && (mipmap_params.m_clamp_height))
    {
        if ((new_width > (int)mipmap_params.m_clamp_width) || (new_height > (int)mipmap_params.m_clamp_height))
        {
            if (mipmap_params.m_clamp_scale)
            {
                new_width = math::minimum<uint>(mipmap_params.m_clamp_width, new_width);
                new_height = math::minimum<uint>(mipmap_params.m_clamp_height, new_height);
            }
        }
    }

    new_width = math::clamp<int>(new_width, 1, cCRNMaxLevelResolution);
    new_height = math::clamp<int>(new_height, 1, cCRNMaxLevelResolution);

    if ((new_width != (int)work_tex.get_width()) || (new_height != (int)work_tex.get_height()))
    {
        console::info(L"Resampling input texture to %ux%u", new_width, new_height);

        const char* pFilter = crn_get_mip_filter_name(mipmap_params.m_filter);

        bool srgb = mipmap_params.m_gamma_filtering != 0;

        dds_texture::resample_params res_params;
        res_params.m_pFilter = pFilter;
        res_params.m_wrapping = mipmap_params.m_tiled != 0;
        if (work_tex.get_num_faces())
            res_params.m_wrapping = false;
        res_params.m_renormalize = mipmap_params.m_renormalize != 0;
        res_params.m_filter_scale = 1.0f;
        res_params.m_gamma = mipmap_params.m_gamma;
        res_params.m_srgb = srgb;
        res_params.m_multithreaded = (params.m_num_helper_threads > 0);

        if (!work_tex.resize(new_width, new_height, res_params))
        {
            console::error(L"Failed resizing texture!");
            return false;
        }
    }

    if ((generate_new_mips) && (generate_mipmaps))
    {
        bool srgb = mipmap_params.m_gamma_filtering != 0;

        const char* pFilter = crn_get_mip_filter_name(mipmap_params.m_filter);

        dds_texture::generate_mipmap_params gen_params;
        gen_params.m_pFilter = pFilter;
        gen_params.m_wrapping = mipmap_params.m_tiled != 0;
        gen_params.m_renormalize = mipmap_params.m_renormalize != 0;
        gen_params.m_filter_scale = mipmap_params.m_blurriness;
        gen_params.m_gamma = mipmap_params.m_gamma;
        gen_params.m_srgb = srgb;
        gen_params.m_multithreaded = params.m_num_helper_threads > 0;
        gen_params.m_max_mips = mipmap_params.m_max_levels;
        gen_params.m_min_mip_size = mipmap_params.m_min_mip_size;

        console::info(L"Generating mipmaps using filter \"%S\"", pFilter);

        timer tm;
        tm.start();
        if (!work_tex.generate_mipmaps(gen_params, true))
        {
            console::error(L"Failed generating mipmaps!");
            return false;
        }
        double t = tm.get_elapsed_secs();

        console::info(L"Generated %u mipmap levels in %3.3fs", work_tex.get_num_levels() - 1, t);
    }

    return true;
}