mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
# refactoring
- color: the sse codepath is now detected and activated from within color.cpp, which avoids making ia32 dependent on the color header. it's called from gamesetup!InitRenderer. - move VFSUtil::EnumDirEnts to vfs.cpp!vfs_dir_enum - allows it to be used from within lib/ without dependency on ps (annoying for other projects) This was SVN commit r3764.
This commit is contained in:
parent
099e860915
commit
6fbce9c355
16 changed files with 136 additions and 142 deletions
|
|
@ -17,3 +17,25 @@ static u32 fallback_ConvertRGBColorTo4ub(const RGBColor& src)
|
|||
// on IA32, this is replaced by an SSE assembly version in ia32.cpp
|
||||
u32 (*ConvertRGBColorTo4ub)(const RGBColor& src) = fallback_ConvertRGBColorTo4ub;
|
||||
|
||||
|
||||
// Assembler-optimized function for color conversion
|
||||
#if CPU_IA32
|
||||
extern "C" u32 sse_ConvertRGBColorTo4ub(const RGBColor& src);
|
||||
#endif
|
||||
|
||||
void ColorActivateFastImpl()
|
||||
{
|
||||
if(0)
|
||||
{
|
||||
}
|
||||
#if CPU_IA32
|
||||
else if (ia32_cap(SSE))
|
||||
{
|
||||
ConvertRGBColorTo4ub = sse_ConvertRGBColorTo4ub;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
debug_printf("No SSE available. Slow fallback routines will be used.\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,13 @@ struct SColor4ub
|
|||
SColor4ub(u8 _r, u8 _g, u8 _b, u8 _a) : R(_r), G(_g), B(_b), A(_a) { }
|
||||
};
|
||||
|
||||
// exposed as function pointer because it is set at init-time to
|
||||
// one of several implementations depending on CPU caps.
|
||||
extern u32 (*ConvertRGBColorTo4ub)(const RGBColor& src);
|
||||
|
||||
// call once ia32_init has run; detects CPU caps and activates the best
|
||||
// possible codepath.
|
||||
extern void ColorActivateFastImpl();
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -191,12 +191,12 @@ static void GetObjectName_ThunkCb(const char* path, const DirEnt* UNUSED(ent), v
|
|||
|
||||
void CObjectManager::GetAllObjectNames(std::vector<CStr>& names)
|
||||
{
|
||||
VFSUtil::EnumDirEnts("art/actors/", VFSUtil::RECURSIVE, "*.xml",
|
||||
vfs_dir_enum("art/actors/", VFS_DIR_RECURSIVE, "*.xml",
|
||||
GetObjectName_ThunkCb, &names);
|
||||
}
|
||||
|
||||
void CObjectManager::GetPropObjectNames(std::vector<CStr>& names)
|
||||
{
|
||||
VFSUtil::EnumDirEnts("art/actors/props/", VFSUtil::RECURSIVE, "*.xml",
|
||||
vfs_dir_enum("art/actors/props/", VFS_DIR_RECURSIVE, "*.xml",
|
||||
GetObjectName_ThunkCb, &names);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,6 +239,85 @@ LibError vfs_dir_next_ent(const Handle hd, DirEnt* ent, const char* filter)
|
|||
}
|
||||
|
||||
|
||||
// call <cb> for each entry matching <user_filter> (see vfs_next_dirent) in
|
||||
// directory <path>; if flags & VFS_DIR_RECURSIVE, entries in
|
||||
// subdirectories are also returned.
|
||||
//
|
||||
// note: EnumDirEntsCB path and ent are only valid during the callback.
|
||||
LibError vfs_dir_enum(const char* start_path, uint flags, const char* user_filter,
|
||||
DirEnumCB cb, void* context)
|
||||
{
|
||||
debug_assert((flags & ~(VFS_DIR_RECURSIVE)) == 0);
|
||||
const bool recursive = (flags & VFS_DIR_RECURSIVE) != 0;
|
||||
|
||||
char filter_buf[VFS_MAX_PATH];
|
||||
const char* filter = user_filter;
|
||||
bool user_filter_wants_dirs = true;
|
||||
if(user_filter)
|
||||
{
|
||||
if(user_filter[0] != '/')
|
||||
user_filter_wants_dirs = false;
|
||||
|
||||
// we need subdirectories and the caller hasn't already requested them
|
||||
if(recursive && !user_filter_wants_dirs)
|
||||
{
|
||||
snprintf(filter_buf, sizeof(filter_buf), "/|%s", user_filter);
|
||||
filter = filter_buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// note: FIFO queue instead of recursion is much more efficient
|
||||
// (less stack usage; avoids seeks by reading all entries in a
|
||||
// directory consecutively)
|
||||
|
||||
std::queue<const char*> dir_queue;
|
||||
dir_queue.push(file_make_unique_fn_copy(start_path));
|
||||
|
||||
// for each directory:
|
||||
do
|
||||
{
|
||||
// get current directory path from queue
|
||||
// note: can't refer to the queue contents - those are invalidated
|
||||
// as soon as a directory is pushed onto it.
|
||||
PathPackage pp;
|
||||
(void)pp_set_dir(&pp, dir_queue.front());
|
||||
dir_queue.pop();
|
||||
|
||||
Handle hdir = vfs_dir_open(pp.path);
|
||||
if(hdir <= 0)
|
||||
{
|
||||
debug_warn("vfs_open_dir failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
// for each entry (file, subdir) in directory:
|
||||
DirEnt ent;
|
||||
while(vfs_dir_next_ent(hdir, &ent, filter) == 0)
|
||||
{
|
||||
// build complete path (DirEnt only stores entry name)
|
||||
(void)pp_append_file(&pp, ent.name);
|
||||
const char* atom_path = file_make_unique_fn_copy(pp.path);
|
||||
|
||||
if(DIRENT_IS_DIR(&ent))
|
||||
{
|
||||
if(recursive)
|
||||
dir_queue.push(atom_path);
|
||||
|
||||
if(user_filter_wants_dirs)
|
||||
cb(atom_path, &ent, context);
|
||||
}
|
||||
else
|
||||
cb(atom_path, &ent, context);
|
||||
}
|
||||
|
||||
vfs_dir_close(hdir);
|
||||
}
|
||||
while(!dir_queue.empty());
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
|||
|
|
@ -321,6 +321,25 @@ extern LibError vfs_dir_close(Handle& hd);
|
|||
extern LibError vfs_dir_next_ent(Handle hd, DirEnt* ent, const char* filter = 0);
|
||||
|
||||
|
||||
|
||||
// called by EnumDirEnts for each entry in a directory (optionally those in
|
||||
// its subdirectories as well), passing their complete path+name, the info
|
||||
// that would be returned by vfs_next_dirent, and user-specified context.
|
||||
// note: path and ent parameters are only valid during the callback.
|
||||
typedef void (*DirEnumCB)(const char* path, const DirEnt* ent, void* context);
|
||||
|
||||
enum DirEnumFlags
|
||||
{
|
||||
VFS_DIR_RECURSIVE = 1
|
||||
};
|
||||
|
||||
// call <cb> for each entry matching <user_filter> (see vfs_next_dirent) in
|
||||
// directory <path>; if flags & VFS_DIR_RECURSIVE, entries in
|
||||
// subdirectories are also returned.
|
||||
extern LibError vfs_dir_enum(const char* path, uint enum_flags, const char* filter,
|
||||
DirEnumCB cb, void* context);
|
||||
|
||||
|
||||
//
|
||||
// file
|
||||
//
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
|
||||
#include "file_internal.h"
|
||||
|
||||
#include "ps/VFSUtil.h"
|
||||
|
||||
// enough for 64K unique files - ought to suffice.
|
||||
typedef u16 FileId;
|
||||
static const FileId NULL_ID = 0;
|
||||
|
|
@ -159,7 +157,7 @@ public:
|
|||
|
||||
// TODO: only add entries from mount points that have
|
||||
// VFS_MOUNT_ARCHIVE flag set (avoids adding screenshots etc.)
|
||||
VFSUtil::EnumDirEnts("", VFSUtil::RECURSIVE, 0, EntCb, &file_nodes);
|
||||
vfs_dir_enum("", VFS_DIR_RECURSIVE, 0, EntCb, &file_nodes);
|
||||
|
||||
// MAX_IDS is a rather large limit on number of files, but must not
|
||||
// be exceeded (otherwise FileId overflows).
|
||||
|
|
|
|||
|
|
@ -63,9 +63,6 @@ void cpu_init()
|
|||
// the result as required by ANSI C. however, FPU calculation
|
||||
// results were changed significantly, so it had to be disabled.
|
||||
//ia32_control87(IA32_RC_CHOP, IA32_MCW_RC);
|
||||
|
||||
// If possible, hook up capability-sensitive assembler routines
|
||||
ia32_hook_capabilities();
|
||||
#endif
|
||||
|
||||
// detects CPU clock frequency and capabilities, which are prerequisites
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@
|
|||
#include "lib/sysdep/win/wtime.h"
|
||||
#endif
|
||||
|
||||
#define NO_COLOR
|
||||
|
||||
#ifndef NO_COLOR
|
||||
#include "graphics/Color.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -684,30 +678,6 @@ LibError ia32_get_call_target(void* ret_addr, void** target)
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef NO_COLOR
|
||||
// Assembler-optimized function for color conversion
|
||||
extern "C" {
|
||||
u32 sse_ConvertRGBColorTo4ub(const RGBColor& src);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ia32_hook_capabilities()
|
||||
{
|
||||
#ifndef NO_COLOR
|
||||
if (ia32_cap(SSE))
|
||||
{
|
||||
ConvertRGBColorTo4ub = sse_ConvertRGBColorTo4ub;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("No SSE available. Slow fallback routines will be used.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// built-in self test
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ extern bool ia32_cap(CpuCap cap);
|
|||
|
||||
|
||||
extern void ia32_get_cpu_info(void);
|
||||
extern void ia32_hook_capabilities(void);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -693,6 +693,8 @@ static void InitRenderer()
|
|||
vp.m_Width=g_xres;
|
||||
vp.m_Height=g_yres;
|
||||
g_Renderer.SetViewport(vp);
|
||||
|
||||
ColorActivateFastImpl();
|
||||
}
|
||||
|
||||
static void InitSDL()
|
||||
|
|
|
|||
|
|
@ -882,7 +882,7 @@ static void LoadUnitUIThunk( const char* path, const DirEnt* UNUSED(ent), void*
|
|||
}
|
||||
int CSelectedEntities::loadUnitUITextures()
|
||||
{
|
||||
THROW_ERR( VFSUtil::EnumDirEnts( "art/textures/ui/session/icons/", VFSUtil::RECURSIVE,
|
||||
THROW_ERR( vfs_dir_enum( "art/textures/ui/session/icons/", VFS_DIR_RECURSIVE,
|
||||
NULL, LoadUnitUIThunk, &m_unitUITextures ) );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,82 +41,3 @@ bool VFSUtil::FindFiles (const CStr& dirname, const char* filter, FileList& file
|
|||
|
||||
}
|
||||
|
||||
|
||||
// call <cb> for each entry matching <user_filter> (see vfs_next_dirent) in
|
||||
// directory <path>; if <recursive>, entries in subdirectories are
|
||||
// also returned.
|
||||
//
|
||||
// note: EnumDirEntsCB path and ent are only valid during the callback.
|
||||
LibError VFSUtil::EnumDirEnts(const CStr start_path, int flags, const char* user_filter,
|
||||
EnumDirEntsCB cb, void* context)
|
||||
{
|
||||
debug_assert((flags & ~(RECURSIVE)) == 0);
|
||||
const bool recursive = (flags & RECURSIVE) != 0;
|
||||
|
||||
char filter_buf[VFS_MAX_PATH];
|
||||
const char* filter = user_filter;
|
||||
bool want_dir = true;
|
||||
if(user_filter)
|
||||
{
|
||||
if(user_filter[0] != '/')
|
||||
want_dir = false;
|
||||
|
||||
// we need subdirectories and the caller hasn't already requested them
|
||||
if(recursive && !want_dir)
|
||||
{
|
||||
snprintf(filter_buf, sizeof(filter_buf), "/|%s", user_filter);
|
||||
filter = filter_buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// note: FIFO queue instead of recursion is much more efficient
|
||||
// (less stack usage; avoids seeks by reading all entries in a
|
||||
// directory consecutively)
|
||||
|
||||
std::queue<const char*> dir_queue;
|
||||
dir_queue.push(file_make_unique_fn_copy(start_path.c_str()));
|
||||
|
||||
// for each directory:
|
||||
do
|
||||
{
|
||||
// get current directory path from queue
|
||||
// note: can't refer to the queue contents - those are invalidated
|
||||
// as soon as a directory is pushed onto it.
|
||||
PathPackage pp;
|
||||
(void)pp_set_dir(&pp, dir_queue.front());
|
||||
dir_queue.pop();
|
||||
|
||||
Handle hdir = vfs_dir_open(pp.path);
|
||||
if(hdir <= 0)
|
||||
{
|
||||
debug_warn("vfs_open_dir failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
// for each entry (file, subdir) in directory:
|
||||
DirEnt ent;
|
||||
while(vfs_dir_next_ent(hdir, &ent, filter) == 0)
|
||||
{
|
||||
// build complete path (DirEnt only stores entry name)
|
||||
(void)pp_append_file(&pp, ent.name);
|
||||
const char* atom_path = file_make_unique_fn_copy(pp.path);
|
||||
|
||||
if(DIRENT_IS_DIR(&ent))
|
||||
{
|
||||
if(recursive)
|
||||
dir_queue.push(atom_path);
|
||||
|
||||
if(want_dir)
|
||||
cb(atom_path, &ent, context);
|
||||
}
|
||||
else
|
||||
cb(atom_path, &ent, context);
|
||||
}
|
||||
|
||||
vfs_dir_close(hdir);
|
||||
}
|
||||
while(!dir_queue.empty());
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,23 +13,4 @@ typedef std::vector<CStr> FileList;
|
|||
// On failure, logs an error and returns false.
|
||||
extern bool FindFiles(const CStr& dirname, const char* filter, FileList& files);
|
||||
|
||||
|
||||
// called by EnumDirEnts for each entry in a directory (optionally those in
|
||||
// its subdirectories as well), passing their complete path+name, the info
|
||||
// that would be returned by vfs_next_dirent, and user-specified context.
|
||||
// note: path and ent parameters are only valid during the callback.
|
||||
typedef void (*EnumDirEntsCB)(const char* path, const DirEnt* ent,
|
||||
void* context);
|
||||
|
||||
enum EnumDirEntsFlags
|
||||
{
|
||||
RECURSIVE = 1
|
||||
};
|
||||
|
||||
// call <cb> for each entry matching <user_filter> (see vfs_next_dirent) in
|
||||
// directory <path>; if flags & RECURSIVE, entries in subdirectories are
|
||||
// also returned.
|
||||
extern LibError EnumDirEnts(const CStr path, int flags, const char* filter,
|
||||
EnumDirEntsCB cb, void* context);
|
||||
|
||||
} // namespace VFSUtil
|
||||
|
|
|
|||
|
|
@ -99,12 +99,12 @@ JSBool JSI_VFS::BuildFileList( JSContext* cx, JSObject* UNUSED(obj), uintN argc,
|
|||
if( !ToPrimitive<bool>( cx, argv[2], recursive ) )
|
||||
return( JS_FALSE );
|
||||
}
|
||||
int flags = recursive? VFSUtil::RECURSIVE : 0;
|
||||
int flags = recursive? VFS_DIR_RECURSIVE : 0;
|
||||
|
||||
|
||||
// build array in the callback function
|
||||
BuildFileListState state(cx);
|
||||
VFSUtil::EnumDirEnts( path, flags, filter, BuildFileListCB, &state );
|
||||
vfs_dir_enum( path, flags, filter, BuildFileListCB, &state );
|
||||
|
||||
*rval = OBJECT_TO_JSVAL( state.filename_array );
|
||||
return( JS_TRUE );
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static void LoadFileThunk( const char* path, const DirEnt* UNUSED(ent), void* co
|
|||
int CBaseEntityCollection::loadTemplates()
|
||||
{
|
||||
// Load all files in entities/ and its subdirectories.
|
||||
THROW_ERR( VFSUtil::EnumDirEnts( "entities/", VFSUtil::RECURSIVE, "*.xml",
|
||||
THROW_ERR( vfs_dir_enum( "entities/", VFS_DIR_RECURSIVE, "*.xml",
|
||||
LoadFileThunk, this ) );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static void LoadFormationThunk( const char* path, const DirEnt* UNUSED(ent), voi
|
|||
int CBaseFormationCollection::loadTemplates()
|
||||
{
|
||||
// Load all files in entities/formations and subdirectories.
|
||||
THROW_ERR( VFSUtil::EnumDirEnts( "entities/formations", VFSUtil::RECURSIVE, "*.xml",
|
||||
THROW_ERR( vfs_dir_enum( "entities/formations", VFS_DIR_RECURSIVE, "*.xml",
|
||||
LoadFormationThunk, this ) );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue