# 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:
janwas 2006-04-14 06:32:05 +00:00
parent 099e860915
commit 6fbce9c355
16 changed files with 136 additions and 142 deletions

View file

@ -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");
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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;
}
///////////////////////////////////////////////////////////////////////////////
//

View file

@ -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
//

View 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).

View file

@ -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

View file

@ -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
//----------------------------------------------------------------------------

View file

@ -113,7 +113,6 @@ extern bool ia32_cap(CpuCap cap);
extern void ia32_get_cpu_info(void);
extern void ia32_hook_capabilities(void);
//-----------------------------------------------------------------------------

View file

@ -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()

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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 );

View file

@ -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;
}

View file

@ -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;
}