示例#1
0
void Interface::DeleteRwObject( RwObject *obj )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    // Delete it using the type system.
    GenericRTTI *rttiObj = engineInterface->typeSystem.GetTypeStructFromAbstractObject( obj );

    if ( rttiObj )
    {
        // By default, we can destroy.
        bool canDestroy = true;

        // If we have the refcount plugin, we want to handle things with it.
        if ( refCountManager *refMan = refCountRegister.GetPluginStruct( engineInterface ) )
        {
            if ( refCountPlugin *refCountObj = RwTypeSystem::RESOLVE_STRUCT <refCountPlugin> ( engineInterface, rttiObj, engineInterface->rwobjTypeInfo, refMan->pluginOffset ) )
            {
                canDestroy = refCountObj->RemoveRef();
            }
        }

        if ( canDestroy )
        {
            engineInterface->typeSystem.Destroy( engineInterface, rttiObj );
        }
    }
}
示例#2
0
void registerTXDPlugins( void )
{
    // First register the main serialization plugins.
    // Those are responsible for detecting texture dictionaries and native textures in RW streams.
    // The sub module plugins depend on those.
    texDictionaryStreamStore.RegisterPlugin( engineFactory );
    registerNativeTexturePlugins();

    // Register pure sub modules.
    registerResizeFilteringEnvironment();
}
示例#3
0
// Interface creation for the RenderWare engine.
Interface* CreateEngine( LibraryVersion theVersion )
{
    if ( hasInitialized == false )
    {
        // Verify data constants before we create a valid engine.
        if ( VerifyLibraryIntegrity() )
        {
            // Configuration comes first.
            registerConfigurationEnvironment();

            // Initialize our plugins first.
            refCountRegister.RegisterPlugin( engineFactory );
            rwlockProvider.RegisterPlugin( engineFactory );

            // Now do the main modules.
            registerThreadingEnvironment();
            registerWarningHandlerEnvironment();
            registerRasterConsistency();
            registerEventSystem();
            registerStreamGlobalPlugins();
            registerFileSystemDataRepository();
            registerSerializationPlugins();
            registerObjectExtensionsPlugins();
            registerTXDPlugins();
            registerImagingPlugin();
            registerWindowingSystem();
            registerDriverEnvironment();
            registerDrawingLayerEnvironment();

            // After all plugins registered themselves, we know that
            // each configuration entry is properly initialized.
            // Now we can create a configuration block in the interface!
            registerConfigurationBlockDispatching();

            hasInitialized = true;
        }
    }

    Interface *engineOut = NULL;

    if ( hasInitialized == true )
    {
        // Create a specialized engine depending on the version.
        engineOut = engineFactory.Construct( _engineMemAlloc );

        if ( engineOut )
        {
            engineOut->SetVersion( theVersion );
        }
    }

    return engineOut;
}
示例#4
0
const TexDictionary* ToConstTexDictionary( Interface *intf, const RwObject *rwObj )
{
    EngineInterface *engineInterface = (EngineInterface*)intf;

    texDictionaryStreamPlugin *txdStream = texDictionaryStreamStore.GetPluginStruct( engineInterface );

    if ( txdStream )
    {
        return txdStream->ToConstTexDictionary( engineInterface, rwObj );
    }

    return NULL;
}
示例#5
0
void ReleaseObject( RwObject *obj )
{
    EngineInterface *engineInterface = (EngineInterface*)obj->engineInterface;

    // Increase the reference count.
    if ( refCountManager *refMan = refCountRegister.GetPluginStruct( (EngineInterface*)engineInterface ) )
    {
        if ( refCountPlugin *refCount = refMan->GetPluginStruct( engineInterface, obj ) )
        {
            // We just delete the object.
            engineInterface->DeleteRwObject( obj );
        }
    }
}
示例#6
0
TexDictionary* CreateTexDictionary( Interface *intf )
{
    EngineInterface *engineInterface = (EngineInterface*)intf;

    TexDictionary *texDictOut = NULL;

    texDictionaryStreamPlugin *txdStream = texDictionaryStreamStore.GetPluginStruct( engineInterface );

    if ( txdStream )
    {
        texDictOut = txdStream->CreateTexDictionary( engineInterface );
    }

    return texDictOut;
}
示例#7
0
namespace fsrandom
{

static fsLockProvider _fileSysRNGLockProvider;

struct fsRandomGeneratorEnv
{
    inline void Initialize( CFileSystemNative *fsys )
    {
        return;
    }

    inline void Shutdown( CFileSystemNative *fsys )
    {
        return;
    }

    inline void operator = ( const fsRandomGeneratorEnv& right )
    {
        // Cannot assign random number generators.
        return;
    }

    // This may not be available on all systems.
    std::random_device _true_random;
};

static PluginDependantStructRegister <fsRandomGeneratorEnv, fileSystemFactory_t> fsRandomGeneratorRegister;

inline fsRandomGeneratorEnv* GetRandomEnv( CFileSystem *fsys )
{
    return fsRandomGeneratorRegister.GetPluginStruct( (CFileSystemNative*)fsys );
}

unsigned long getSystemRandom( CFileSystem *sys )
{
    fsRandomGeneratorEnv *env = GetRandomEnv( sys );

    assert( env != NULL );

    // Not sure whether std::random_device is thread-safe, so be careful here.
    NativeExecutive::CReadWriteWriteContextSafe <> consistency( _fileSysRNGLockProvider.GetReadWriteLock( sys ) );

    return env->_true_random();
}

};
示例#8
0
uint32 GetRefCount( RwObject *obj )
{
    uint32 refCountNum = 1;    // If we do not support reference counting, this is actually a valid value.

    EngineInterface *engineInterface = (EngineInterface*)obj->engineInterface;

    // Increase the reference count.
    if ( refCountManager *refMan = refCountRegister.GetPluginStruct( engineInterface ) )
    {
        if ( refCountPlugin *refCount = refMan->GetPluginStruct( engineInterface, obj ) )
        {
            // We just delete the object.
            refCountNum = refCount->refCount;
        }
    }

    return refCountNum;
}
示例#9
0
// Acquisition routine for objects, so that reference counting is increased, if needed.
// Can return NULL if the reference count could not be increased.
RwObject* AcquireObject( RwObject *obj )
{
    EngineInterface *engineInterface = (EngineInterface*)obj->engineInterface;

    // Increase the reference count.
    if ( refCountManager *refMan = refCountRegister.GetPluginStruct( engineInterface ) )
    {
        if ( refCountPlugin *refCount = refMan->GetPluginStruct( engineInterface, obj ) )
        {
            // TODO: make sure that incrementing is actually possible.
            // we cannot increment if we would overflow the number, for instance.

            refCount->AddRef();
        }
    }

    return obj;
}
示例#10
0
void registerD3D8NativePlugin( void )
{
    d3dNativeTexturePluginRegister.RegisterPlugin( engineFactory );
}
示例#11
0
namespace rw
{

struct resizeFilterBlurPlugin : public rasterResizeFilterInterface
{
    void GetSupportedFiltering( resizeFilteringCaps& capsOut ) const override
    {
        capsOut.supportsMagnification = false;
        capsOut.supportsMinification = true;
        capsOut.magnify2D = false;
        capsOut.minify2D = true;
    }

    void MagnifyFiltering(
        const resizeColorPipeline& srcBmp, uint32 magX, uint32 magY, uint32 magScaleX, uint32 magScaleY,
        resizeColorPipeline& dstBmp, uint32 dstX, uint32 dstY
    ) const override
    {
        // TODO.
        throw RwException( "not supported yet" );
    }

    void MinifyFiltering(
        const resizeColorPipeline& srcBmp, uint32 minX, uint32 minY, uint32 minScaleX, uint32 minScaleY,
        abstractColorItem& colorItem
    ) const override
    {
        eColorModel model = srcBmp.getColorModel();

        if ( model == COLORMODEL_RGBA )
        {
            uint32 redSumm = 0;
            uint32 greenSumm = 0;
            uint32 blueSumm = 0;
            uint32 alphaSumm = 0;

            // Loop through the texels and calculate a blur.
            uint32 addCount = 0;

            for ( uint32 y = 0; y < minScaleY; y++ )
            {
                for ( uint32 x = 0; x < minScaleX; x++ )
                {
                    abstractColorItem srcColorItem;

                    bool hasColor = srcBmp.fetchcolor(
                        x + minX, y + minY,
                        srcColorItem
                    );

                    if ( hasColor )
                    {
                        // Add colors together.
                        redSumm += srcColorItem.rgbaColor.r;
                        greenSumm += srcColorItem.rgbaColor.g;
                        blueSumm += srcColorItem.rgbaColor.b;
                        alphaSumm += srcColorItem.rgbaColor.a;

                        addCount++;
                    }
                }
            }

            if ( addCount != 0 )
            {
                // Calculate the real color.
                colorItem.rgbaColor.r = std::min( redSumm / addCount, 255u );
                colorItem.rgbaColor.g = std::min( greenSumm / addCount, 255u );
                colorItem.rgbaColor.b = std::min( blueSumm / addCount, 255u );
                colorItem.rgbaColor.a = std::min( alphaSumm / addCount, 255u );

                colorItem.model = COLORMODEL_RGBA;
            }
        }
        else if ( model == COLORMODEL_LUMINANCE )
        {
            uint32 lumSumm = 0;
            uint32 alphaSumm = 0;

            // Loop through the texels and calculate a blur.
            uint32 addCount = 0;

            for ( uint32 y = 0; y < minScaleY; y++ )
            {
                for ( uint32 x = 0; x < minScaleX; x++ )
                {
                    abstractColorItem srcColorItem;

                    bool hasColor = srcBmp.fetchcolor(
                        x + minX, y + minY,
                        srcColorItem
                    );

                    if ( hasColor )
                    {
                        // Add colors together.
                        lumSumm += srcColorItem.luminance.lum;
                        alphaSumm += srcColorItem.luminance.alpha;

                        addCount++;
                    }
                }
            }

            if ( addCount != 0 )
            {
                // Calculate the real color.
                colorItem.luminance.lum = std::min( lumSumm / addCount, 255u );
                colorItem.luminance.alpha = std::min( alphaSumm / addCount, 255u );

                colorItem.model = COLORMODEL_LUMINANCE;
            }
        }
    }

    inline void Initialize( EngineInterface *engineInterface )
    {
        RegisterResizeFiltering( engineInterface, "blur", this );
    }

    inline void Shutdown( EngineInterface *engineInterface )
    {
        UnregisterResizeFiltering( engineInterface, this );
    }
};

static PluginDependantStructRegister <resizeFilterBlurPlugin, RwInterfaceFactory_t> resizeFilterBlurPluginRegister;

void registerRasterSizeBlurPlugin( void )
{
    resizeFilterBlurPluginRegister.RegisterPlugin( engineFactory );
}

};
示例#12
0
void registerRasterSizeBlurPlugin( void )
{
    resizeFilterBlurPluginRegister.RegisterPlugin( engineFactory );
}
示例#13
0
inline fsRandomGeneratorEnv* GetRandomEnv( CFileSystem *fsys )
{
    return fsRandomGeneratorRegister.GetPluginStruct( (CFileSystemNative*)fsys );
}
示例#14
0
void registerMobileUNCNativePlugin( void )
{
    uncNativeTexturePlugin.RegisterPlugin( engineFactory );
}
示例#15
0
namespace rw
{

eTexNativeCompatibility uncNativeTextureTypeProvider::IsCompatibleTextureBlock( BlockProvider& inputProvider ) const
{
    eTexNativeCompatibility texCompat = RWTEXCOMPAT_NONE;

    BlockProvider texNativeImageBlock( &inputProvider );

    texNativeImageBlock.EnterContext();

    try
    {
        if ( texNativeImageBlock.getBlockID() == CHUNK_STRUCT )
        {
            // Here we can check the platform descriptor, since we know it is unique.
            uint32 platformDescriptor = texNativeImageBlock.readUInt32();

            if ( platformDescriptor == PLATFORMDESC_UNC_MOBILE )
            {
                texCompat = RWTEXCOMPAT_ABSOLUTE;
            }
        }
    }
    catch( ... )
    {
        texNativeImageBlock.LeaveContext();

        throw;
    }

    texNativeImageBlock.LeaveContext();

    return texCompat;
}

void uncNativeTextureTypeProvider::DeserializeTexture( TextureBase *theTexture, PlatformTexture *nativeTex, BlockProvider& inputProvider ) const
{
    Interface *engineInterface = theTexture->engineInterface;

    // Read the texture native block.
    {
        BlockProvider texImageDataBlock( &inputProvider );

        texImageDataBlock.EnterContext();

        try
        {
            if ( texImageDataBlock.getBlockID() == CHUNK_STRUCT )
            {
                // Read the meta header first.
                mobile_unc::textureNativeGenericHeader metaHeader;

                texImageDataBlock.read( &metaHeader, sizeof( metaHeader ) );

                // Make sure we got the right platform descriptor.
                if ( metaHeader.platformDescriptor != PLATFORMDESC_UNC_MOBILE )
                {
                    throw RwException( "invalid platform descriptor in uncompressed mobile texture native" );
                }

                // Cast out native texture type.
                NativeTextureMobileUNC *platformTex = (NativeTextureMobileUNC*)nativeTex;

                // Read the format info.
                metaHeader.formatInfo.parse( *theTexture );

                // Read the texture names.
                {
                    char tmpbuf[ sizeof( metaHeader.name ) + 1 ];

                    // Make sure the name buffer is zero terminted.
                    tmpbuf[ sizeof( metaHeader.name ) ] = '\0';

                    // Move over the texture name.
                    memcpy( tmpbuf, metaHeader.name, sizeof( metaHeader.name ) );

                    theTexture->SetName( tmpbuf );

                    // Move over the texture mask name.
                    memcpy( tmpbuf, metaHeader.maskName, sizeof( metaHeader.maskName ) );

                    theTexture->SetMaskName( tmpbuf );
                }
                
                // Read some advanced properties.
                bool hasAlpha = metaHeader.hasAlpha;

                platformTex->hasAlpha = hasAlpha;
                
                platformTex->unk2 = metaHeader.unk2;
                platformTex->unk3 = metaHeader.unk3;

                assert( metaHeader.unk1 == false );
                assert( metaHeader.unk2 == 0 );

                // This texture format is very primitive.
                // It supports only RASTER_4444 textures with 16 depth.
                // Everything that this format stores is already storable in the Direct3D 8/9 platform.
                eRasterFormat rasterFormat;
                uint32 depth;
                eColorOrdering colorOrder;

                getUNCRasterFormat( hasAlpha, rasterFormat, colorOrder, depth );

                // Parse all mipmaps.
                // This format is pretty simple.
                uint32 maybeMipmapCount = metaHeader.mipmapCount;

                mipGenLevelGenerator mipLevelGen( metaHeader.width, metaHeader.height );

                if ( !mipLevelGen.isValidLevel() )
                {
                    throw RwException( "texture " + theTexture->GetName() + " has invalid dimensions" );
                }

                uint32 mipmap_index = 0;
                
                uint32 remainingTexImageDataSize = metaHeader.imageDataSectionSize;

                while ( true )
                {
                    if ( remainingTexImageDataSize == 0 )
                    {
                        break;
                    }

                    if ( mipmap_index >= maybeMipmapCount )
                    {
                        break;
                    }

                    bool couldEstablishLevel = true;

                    if ( mipmap_index > 0 )
                    {
                        couldEstablishLevel = mipLevelGen.incrementLevel();
                    }

                    if ( !couldEstablishLevel )
                    {
                        break;
                    }

                    // Create the new mipmap layer.
                    NativeTextureMobileUNC::mipmapLayer newLayer;

                    uint32 width = mipLevelGen.getLevelWidth();
                    uint32 height = mipLevelGen.getLevelHeight();

                    newLayer.layerWidth = width;
                    newLayer.layerHeight = height;

                    // Since we are an uncompressed texture, the layer dimensions equal the raw dimensions.
                    newLayer.width = width;
                    newLayer.height = height;

                    // Calculate the size of this layer.
                    uint32 texRowSize = getUNCRasterDataRowSize( width, depth );

                    uint32 texDataSize = getRasterDataSizeByRowSize( texRowSize, height );

                    // Reduce the texture image data section remainder.
                    if ( remainingTexImageDataSize < texDataSize )
                    {
                        throw RwException( "texture " + theTexture->GetName() + " has an invalid image data stream section size" );
                    }

                    remainingTexImageDataSize -= texDataSize;

                    // Store the texels.
                    texImageDataBlock.check_read_ahead( texDataSize );

                    void *texels = engineInterface->PixelAllocate( texDataSize );

                    try
                    {
                        texImageDataBlock.read( texels, texDataSize );
                    }
                    catch( ... )
                    {
                        engineInterface->PixelFree( texels );

                        throw;
                    }

                    newLayer.texels = texels;
                    newLayer.dataSize = texDataSize;

                    // Store this layer.
                    platformTex->mipmaps.push_back( newLayer );

                    // Increase the mipmap index.
                    mipmap_index++;
                }

                // We do not want no empty textures.
                if ( mipmap_index == 0 )
                {
                    throw RwException( "texture " + theTexture->GetName() + " is empty" );
                }

                // Fix filtering mode.
                fixFilteringMode( *theTexture, mipmap_index );

                int warningLevel = engineInterface->GetWarningLevel();

                // Check whether we have any remaining texture image data.
                if ( remainingTexImageDataSize != 0 )
                {
                    if ( warningLevel >= 3 )
                    {
                        engineInterface->PushWarning( "texture " + theTexture->GetName() + " has image data section meta-data" );
                    }

                    // Skip the meta-data.
                    texImageDataBlock.skip( remainingTexImageDataSize );
                }

                // We are done!
            }
            else
            {
                throw RwException( "could not find tex image data block in uncompressed mobile texture native" );
            }
        }
        catch( ... )
        {
            texImageDataBlock.LeaveContext();

            throw;
        }

        texImageDataBlock.LeaveContext();
    }

    // Deserialize extensions.
    engineInterface->DeserializeExtensions( theTexture, inputProvider );
}

static PluginDependantStructRegister <uncNativeTextureTypeProvider, RwInterfaceFactory_t> uncNativeTexturePlugin;

void registerMobileUNCNativePlugin( void )
{
    uncNativeTexturePlugin.RegisterPlugin( engineFactory );
}

};
示例#16
0
namespace rw
{

struct raster_constructor
{
    EngineInterface *intf;
    void *constr_params;

    inline Raster* Construct( void *mem ) const
    {
        return new (mem) Raster( this->intf, this->constr_params );
    }
};

void EngineInterface::rasterTypeInterface::Construct( void *mem, EngineInterface *intf, void *constr_params ) const
{
    raster_constructor constr;
    constr.intf = intf;
    constr.constr_params = constr_params;

    intf->rasterPluginFactory.ConstructPlacementEx( mem, constr );
}

void EngineInterface::rasterTypeInterface::CopyConstruct( void *mem, const void *srcMem ) const
{
    engineInterface->rasterPluginFactory.ClonePlacement( mem, (const rw::Raster*)srcMem );
}

void EngineInterface::rasterTypeInterface::Destruct( void *mem ) const
{
    engineInterface->rasterPluginFactory.DestroyPlacement( (rw::Raster*)mem );
}

size_t EngineInterface::rasterTypeInterface::GetTypeSize( EngineInterface *intf, void *constr_params ) const
{
    return intf->rasterPluginFactory.GetClassSize();
}

size_t EngineInterface::rasterTypeInterface::GetTypeSizeByObject( EngineInterface *intf, const void *mem ) const
{
    return intf->rasterPluginFactory.GetClassSize();
}

// Factory for interfaces.
RwMemoryAllocator _engineMemAlloc;

RwInterfaceFactory_t engineFactory;

EngineInterface::EngineInterface( void )
{
    // Set up the type system.
    this->typeSystem._memAlloc = &memAlloc;
    this->typeSystem.lockProvider.engineInterface = this;

    this->typeSystem.InitializeLockProvider();

    // Set up some type interfaces.
    this->_rasterTypeInterface.engineInterface = this;

    // Register the main RenderWare types.
    {
        this->streamTypeInfo = this->typeSystem.RegisterAbstractType <Stream> ( "stream" );
        this->rasterTypeInfo = this->typeSystem.RegisterType( "raster", &this->_rasterTypeInterface );
        this->rwobjTypeInfo = this->typeSystem.RegisterAbstractType <RwObject> ( "rwobj" );
        this->textureTypeInfo = this->typeSystem.RegisterStructType <TextureBase> ( "texture", this->rwobjTypeInfo );
    }
}

RwObject::RwObject( Interface *engineInterface, void *construction_params )
{
    // Constructor that is called for creation.
    this->engineInterface = engineInterface;
    this->objVersion = engineInterface->GetVersion();   // when creating an object, we assign it the current version.
}

inline void SafeDeleteType( EngineInterface *engineInterface, RwTypeSystem::typeInfoBase*& theType )
{
    RwTypeSystem::typeInfoBase *theTypeVal = theType;

    if ( theTypeVal )
    {
        engineInterface->typeSystem.DeleteType( theTypeVal );

        theType = NULL;
    }
}

EngineInterface::~EngineInterface( void )
{
    // Unregister all types again.
    {
        SafeDeleteType( this, this->textureTypeInfo );
        SafeDeleteType( this, this->rwobjTypeInfo );
        SafeDeleteType( this, this->rasterTypeInfo );
        SafeDeleteType( this, this->streamTypeInfo );
    }
}

rwLockProvider_t rwlockProvider;

void Interface::SetVersion( LibraryVersion version )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetVersion( version );
}

LibraryVersion Interface::GetVersion( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetVersion();
}

void Interface::SetApplicationInfo( const softwareMetaInfo& metaInfo )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    scoped_rwlock_writer <rwlock> lock( GetReadWriteLock( engineInterface ) );

    if ( const char *appName = metaInfo.applicationName )
    {
        engineInterface->applicationName = appName;
    }
    else
    {
        engineInterface->applicationName.clear();
    }

    if ( const char *appVersion = metaInfo.applicationVersion )
    {
        engineInterface->applicationVersion = appVersion;
    }
    else
    {
        engineInterface->applicationVersion.clear();
    }

    if ( const char *desc = metaInfo.description )
    {
        engineInterface->applicationDescription = desc;
    }
    else
    {
        engineInterface->applicationDescription.clear();
    }
}

void Interface::SetMetaDataTagging( bool enabled )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetMetaDataTagging( enabled );
}

bool Interface::GetMetaDataTagging( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetMetaDataTagging();
}

std::string GetRunningSoftwareInformation( EngineInterface *engineInterface, bool outputShort )
{
    std::string infoOut;

    {
        scoped_rwlock_reader <rwlock> lock( GetReadWriteLock( engineInterface ) );

        const rwConfigBlock& cfgBlock = GetConstEnvironmentConfigBlock( engineInterface );

        // Only output anything if we enable meta data tagging.
        if ( cfgBlock.GetMetaDataTagging() )
        {
            // First put the software name.
            bool hasAppName = false;

            if ( engineInterface->applicationName.length() != 0 )
            {
                infoOut += engineInterface->applicationName;

                hasAppName = true;
            }
            else
            {
                infoOut += "RenderWare (generic)";
            }

            infoOut += " [rwver: " + engineInterface->GetVersion().toString() + "]";

            if ( hasAppName )
            {
                if ( engineInterface->applicationVersion.length() != 0 )
                {
                    infoOut += " version: " + engineInterface->applicationVersion;
                }
            }

            if ( outputShort == false )
            {
                if ( engineInterface->applicationDescription.length() != 0 )
                {
                    infoOut += " " + engineInterface->applicationDescription;
                }
            }
        }
    }

    return infoOut;
}

struct refCountPlugin
{
    std::atomic <unsigned long> refCount;

    inline void operator =( const refCountPlugin& right )
    {
        this->refCount.store( right.refCount );
    }

    inline void Initialize( GenericRTTI *obj )
    {
        this->refCount = 1; // we start off with one.
    }

    inline void Shutdown( GenericRTTI *obj )
    {
        // Has to be zeroed by the manager.
        assert( this->refCount == 0 );
    }

    inline void AddRef( void )
    {
        this->refCount++;
    }

    inline bool RemoveRef( void )
    {
        return ( this->refCount.fetch_sub( 1 ) == 1 );
    }
};

struct refCountManager
{
    inline void Initialize( EngineInterface *engineInterface )
    {
        this->pluginOffset =
            engineInterface->typeSystem.RegisterDependantStructPlugin <refCountPlugin> ( engineInterface->rwobjTypeInfo, RwTypeSystem::ANONYMOUS_PLUGIN_ID );
    }

    inline void Shutdown( EngineInterface *engineInterface )
    {
        engineInterface->typeSystem.UnregisterPlugin( engineInterface->rwobjTypeInfo, this->pluginOffset );
    }

    inline refCountPlugin* GetPluginStruct( EngineInterface *engineInterface, RwObject *obj )
    {
        GenericRTTI *rtObj = RwTypeSystem::GetTypeStructFromObject( obj );

        return RwTypeSystem::RESOLVE_STRUCT <refCountPlugin> ( engineInterface, rtObj, engineInterface->rwobjTypeInfo, this->pluginOffset );
    }

    RwTypeSystem::pluginOffset_t pluginOffset;
};

static PluginDependantStructRegister <refCountManager, RwInterfaceFactory_t> refCountRegister;

// Acquisition routine for objects, so that reference counting is increased, if needed.
// Can return NULL if the reference count could not be increased.
RwObject* AcquireObject( RwObject *obj )
{
    EngineInterface *engineInterface = (EngineInterface*)obj->engineInterface;

    // Increase the reference count.
    if ( refCountManager *refMan = refCountRegister.GetPluginStruct( engineInterface ) )
    {
        if ( refCountPlugin *refCount = refMan->GetPluginStruct( engineInterface, obj ) )
        {
            // TODO: make sure that incrementing is actually possible.
            // we cannot increment if we would overflow the number, for instance.

            refCount->AddRef();
        }
    }

    return obj;
}

void ReleaseObject( RwObject *obj )
{
    EngineInterface *engineInterface = (EngineInterface*)obj->engineInterface;

    // Increase the reference count.
    if ( refCountManager *refMan = refCountRegister.GetPluginStruct( (EngineInterface*)engineInterface ) )
    {
        if ( refCountPlugin *refCount = refMan->GetPluginStruct( engineInterface, obj ) )
        {
            // We just delete the object.
            engineInterface->DeleteRwObject( obj );
        }
    }
}

uint32 GetRefCount( RwObject *obj )
{
    uint32 refCountNum = 1;    // If we do not support reference counting, this is actually a valid value.

    EngineInterface *engineInterface = (EngineInterface*)obj->engineInterface;

    // Increase the reference count.
    if ( refCountManager *refMan = refCountRegister.GetPluginStruct( engineInterface ) )
    {
        if ( refCountPlugin *refCount = refMan->GetPluginStruct( engineInterface, obj ) )
        {
            // We just delete the object.
            refCountNum = refCount->refCount;
        }
    }

    return refCountNum;
}

RwObject* Interface::ConstructRwObject( const char *typeName )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    RwObject *newObj = NULL;

    if ( RwTypeSystem::typeInfoBase *rwobjTypeInfo = engineInterface->rwobjTypeInfo )
    {
        // Try to find a type that inherits from RwObject with this name.
        RwTypeSystem::typeInfoBase *rwTypeInfo = engineInterface->typeSystem.FindTypeInfo( typeName, rwobjTypeInfo );

        if ( rwTypeInfo )
        {
            // Try to construct us.
            GenericRTTI *rtObj = engineInterface->typeSystem.Construct( engineInterface, rwTypeInfo, NULL );

            if ( rtObj )
            {
                // We are successful! Return the new object.
                newObj = (RwObject*)RwTypeSystem::GetObjectFromTypeStruct( rtObj );
            }
        }
    }

    return newObj;
}

RwObject* Interface::CloneRwObject( const RwObject *srcObj )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    RwObject *newObj = NULL;

    // We simply use our type system to do the job.
    const GenericRTTI *rttiObj = engineInterface->typeSystem.GetTypeStructFromConstAbstractObject( srcObj );

    if ( rttiObj )
    {
        GenericRTTI *newRtObj = engineInterface->typeSystem.Clone( engineInterface, rttiObj );

        if ( newRtObj )
        {
            newObj = (RwObject*)RwTypeSystem::GetObjectFromTypeStruct( newRtObj );
        }
    }

    return newObj;
}

void Interface::DeleteRwObject( RwObject *obj )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    // Delete it using the type system.
    GenericRTTI *rttiObj = engineInterface->typeSystem.GetTypeStructFromAbstractObject( obj );

    if ( rttiObj )
    {
        // By default, we can destroy.
        bool canDestroy = true;

        // If we have the refcount plugin, we want to handle things with it.
        if ( refCountManager *refMan = refCountRegister.GetPluginStruct( engineInterface ) )
        {
            if ( refCountPlugin *refCountObj = RwTypeSystem::RESOLVE_STRUCT <refCountPlugin> ( engineInterface, rttiObj, engineInterface->rwobjTypeInfo, refMan->pluginOffset ) )
            {
                canDestroy = refCountObj->RemoveRef();
            }
        }

        if ( canDestroy )
        {
            engineInterface->typeSystem.Destroy( engineInterface, rttiObj );
        }
    }
}

void Interface::GetObjectTypeNames( rwobjTypeNameList_t& listOut ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    if ( RwTypeSystem::typeInfoBase *rwobjTypeInfo = engineInterface->rwobjTypeInfo )
    {
        for ( RwTypeSystem::type_iterator iter = engineInterface->typeSystem.GetTypeIterator(); !iter.IsEnd(); iter.Increment() )
        {
            RwTypeSystem::typeInfoBase *item = iter.Resolve();

            if ( item != rwobjTypeInfo )
            {
                if ( engineInterface->typeSystem.IsTypeInheritingFrom( rwobjTypeInfo, item ) )
                {
                    listOut.push_back( item->name );
                }
            }
        }
    }
}

bool Interface::IsObjectRegistered( const char *typeName ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    if ( RwTypeSystem::typeInfoBase *rwobjTypeInfo = engineInterface->rwobjTypeInfo )
    {
        // Try to find a type that inherits from RwObject with this name.
        RwTypeSystem::typeInfoBase *rwTypeInfo = engineInterface->typeSystem.FindTypeInfo( typeName, rwobjTypeInfo );

        if ( rwTypeInfo )
        {
            return true;
        }
    }

    return false;
}

const char* Interface::GetObjectTypeName( const RwObject *rwObj ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    const char *typeName = "unknown";

    const GenericRTTI *rtObj = engineInterface->typeSystem.GetTypeStructFromConstAbstractObject( rwObj );

    if ( rtObj )
    {
        RwTypeSystem::typeInfoBase *typeInfo = RwTypeSystem::GetTypeInfoFromTypeStruct( rtObj );

        // Return its type name.
        // This is an IMMUTABLE property, so we are safe.
        typeName = typeInfo->name;
    }

    return typeName;
}

void Interface::SetWarningManager( WarningManagerInterface *warningMan )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetWarningManager( warningMan );
}

WarningManagerInterface* Interface::GetWarningManager( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetWarningManager();
}

void Interface::SetWarningLevel( int level )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetWarningLevel( level );
}

int Interface::GetWarningLevel( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetWarningLevel();
}

void Interface::SetIgnoreSecureWarnings( bool doIgnore )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetIgnoreSecureWarnings( doIgnore );
}

bool Interface::GetIgnoreSecureWarnings( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetIgnoreSecureWarnings();
}

bool Interface::SetPaletteRuntime( ePaletteRuntimeType palRunType )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    return GetEnvironmentConfigBlock( engineInterface ).SetPaletteRuntime( palRunType );
}

ePaletteRuntimeType Interface::GetPaletteRuntime( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetPaletteRuntime();
}

void Interface::SetDXTRuntime( eDXTCompressionMethod dxtRunType )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetDXTRuntime( dxtRunType );
}

eDXTCompressionMethod Interface::GetDXTRuntime( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetDXTRuntime();
}

void Interface::SetFixIncompatibleRasters( bool doFix )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetFixIncompatibleRasters( doFix );
}

bool Interface::GetFixIncompatibleRasters( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetFixIncompatibleRasters();
}

void Interface::SetCompatTransformNativeImaging( bool transfEnable )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetCompatTransformNativeImaging( transfEnable );
}

bool Interface::GetCompatTransformNativeImaging( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetCompatTransformNativeImaging();
}

void Interface::SetPreferPackedSampleExport( bool preferPacked )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetPreferPackedSampleExport( preferPacked );
}

bool Interface::GetPreferPackedSampleExport( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetPreferPackedSampleExport();
}

void Interface::SetDXTPackedDecompression( bool packedDecompress )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetDXTPackedDecompression( packedDecompress );
}

bool Interface::GetDXTPackedDecompression( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetDXTPackedDecompression();
}

void Interface::SetIgnoreSerializationBlockRegions( bool doIgnore )
{
    EngineInterface *engineInterface = (EngineInterface*)this;

    GetEnvironmentConfigBlock( engineInterface ).SetIgnoreSerializationBlockRegions( doIgnore );
}

bool Interface::GetIgnoreSerializationBlockRegions( void ) const
{
    const EngineInterface *engineInterface = (const EngineInterface*)this;

    return GetConstEnvironmentConfigBlock( engineInterface ).GetIgnoreSerializationBlockRegions();
}

// Static library object that takes care of initializing the module dependencies properly.
extern void registerConfigurationEnvironment( void );
extern void registerThreadingEnvironment( void );
extern void registerWarningHandlerEnvironment( void );
extern void registerRasterConsistency( void );
extern void registerEventSystem( void );
extern void registerTXDPlugins( void );
extern void registerObjectExtensionsPlugins( void );
extern void registerSerializationPlugins( void );
extern void registerStreamGlobalPlugins( void );
extern void registerFileSystemDataRepository( void );
extern void registerImagingPlugin( void );
extern void registerWindowingSystem( void );
extern void registerDriverEnvironment( void );
extern void registerDrawingLayerEnvironment( void );

extern void registerConfigurationBlockDispatching( void );

static bool hasInitialized = false;

static bool VerifyLibraryIntegrity( void )
{
    // We need to standardize the number formats.
    // One way to check that is to make out their size, I guess.
    // Then there is also the problem of endianness, which we do not check here :(
    // For that we have to add special handling into the serialization environments.
    return
        ( sizeof(uint8) == 1 &&
          sizeof(uint16) == 2 &&
          sizeof(uint32) == 4 &&
          sizeof(uint64) == 8 &&
          sizeof(int8) == 1 &&
          sizeof(int16) == 2 &&
          sizeof(int32) == 4 &&
          sizeof(int64) == 8 &&
          sizeof(float32) == 4 );
}

// Interface creation for the RenderWare engine.
Interface* CreateEngine( LibraryVersion theVersion )
{
    if ( hasInitialized == false )
    {
        // Verify data constants before we create a valid engine.
        if ( VerifyLibraryIntegrity() )
        {
            // Configuration comes first.
            registerConfigurationEnvironment();

            // Initialize our plugins first.
            refCountRegister.RegisterPlugin( engineFactory );
            rwlockProvider.RegisterPlugin( engineFactory );

            // Now do the main modules.
            registerThreadingEnvironment();
            registerWarningHandlerEnvironment();
            registerRasterConsistency();
            registerEventSystem();
            registerStreamGlobalPlugins();
            registerFileSystemDataRepository();
            registerSerializationPlugins();
            registerObjectExtensionsPlugins();
            registerTXDPlugins();
            registerImagingPlugin();
            registerWindowingSystem();
            registerDriverEnvironment();
            registerDrawingLayerEnvironment();

            // After all plugins registered themselves, we know that
            // each configuration entry is properly initialized.
            // Now we can create a configuration block in the interface!
            registerConfigurationBlockDispatching();

            hasInitialized = true;
        }
    }

    Interface *engineOut = NULL;

    if ( hasInitialized == true )
    {
        // Create a specialized engine depending on the version.
        engineOut = engineFactory.Construct( _engineMemAlloc );

        if ( engineOut )
        {
            engineOut->SetVersion( theVersion );
        }
    }

    return engineOut;
}

void DeleteEngine( Interface *theEngine )
{
    assert( hasInitialized == true );

    EngineInterface *engineInterface = (EngineInterface*)theEngine;

    // Kill everything threading related, so we can terminate (WARNING: HACK)
    PurgeActiveThreadingObjects( engineInterface );

    // Destroy the engine again.
    engineFactory.Destroy( _engineMemAlloc, engineInterface );
}

};
示例#17
0
namespace rw
{

void d3d8NativeTextureTypeProvider::DeserializeTexture( TextureBase *theTexture, PlatformTexture *nativeTex, BlockProvider& inputProvider ) const
{
    Interface *engineInterface = theTexture->engineInterface;

    {
        BlockProvider texNativeImageStruct( &inputProvider );

        texNativeImageStruct.EnterContext();

        try
        {
            if ( texNativeImageStruct.getBlockID() == CHUNK_STRUCT )
            {
                d3d8::textureMetaHeaderStructGeneric metaHeader;
                texNativeImageStruct.read( &metaHeader, sizeof(metaHeader) );

	            uint32 platform = metaHeader.platformDescriptor;

	            if (platform != PLATFORM_D3D8)
                {
                    throw RwException( "invalid platform type in Direct3D 8 texture reading" );
                }

                // Recast the texture to our native type.
                NativeTextureD3D8 *platformTex = (NativeTextureD3D8*)nativeTex;

                int engineWarningLevel = engineInterface->GetWarningLevel();

                bool engineIgnoreSecureWarnings = engineInterface->GetIgnoreSecureWarnings();

                // Read the texture names.
                {
                    char tmpbuf[ sizeof( metaHeader.name ) + 1 ];

                    // Make sure the name buffer is zero terminted.
                    tmpbuf[ sizeof( metaHeader.name ) ] = '\0';

                    // Move over the texture name.
                    memcpy( tmpbuf, metaHeader.name, sizeof( metaHeader.name ) );

                    theTexture->SetName( tmpbuf );

                    // Move over the texture mask name.
                    memcpy( tmpbuf, metaHeader.maskName, sizeof( metaHeader.maskName ) );

                    theTexture->SetMaskName( tmpbuf );
                }

                // Read texture format.
                texFormatInfo formatInfo = metaHeader.texFormat;

                formatInfo.parse( *theTexture );

                // Deconstruct the format flags.
                bool hasMipmaps = false;    // TODO: actually use this flag.

                readRasterFormatFlags( metaHeader.rasterFormat, platformTex->rasterFormat, platformTex->paletteType, hasMipmaps, platformTex->autoMipmaps );

	            platformTex->hasAlpha = ( metaHeader.hasAlpha != 0 ? true : false );

                uint32 depth = metaHeader.depth;
                uint32 maybeMipmapCount = metaHeader.mipmapCount;

                platformTex->depth = depth;

                platformTex->rasterType = metaHeader.rasterType;

                // Decide about the color order.
                {
                    eColorOrdering colorOrder = COLOR_BGRA;

                    if ( platformTex->paletteType != PALETTE_NONE )
                    {
                        colorOrder = COLOR_RGBA;
                    }

                    platformTex->colorOrdering = colorOrder;
                }

                // Read compression information.
                {
                    uint32 dxtInfo = metaHeader.dxtCompression;

                    platformTex->dxtCompression = dxtInfo;

                    // If we are compressed, it must be a compression we know about.
                    if ( dxtInfo != 0 )
                    {
                        if ( dxtInfo != 1 && dxtInfo != 2 && dxtInfo != 3 && dxtInfo != 4 && dxtInfo != 5 )
                        {
                            throw RwException( "invalid Direct3D texture compression format" );
                        }
                    }
                }

                // Verify raster properties and attempt to fix broken textures.
                // Broken textures travel with mods like San Andreas Retextured.
                // - Verify depth.
                {
                    bool hasInvalidDepth = false;

                    if (platformTex->paletteType == PALETTE_4BIT)
                    {
                        if (depth != 4 && depth != 8)
                        {
                            hasInvalidDepth = true;
                        }
                    }
                    else if (platformTex->paletteType == PALETTE_8BIT)
                    {
                        if (depth != 8)
                        {
                            hasInvalidDepth = true;
                        }
                    }

                    if (hasInvalidDepth == true)
                    {
                        throw RwException( "texture " + theTexture->GetName() + " has an invalid depth" );

                        // We cannot fix an invalid depth.
                    }
                }
                
                if (platformTex->paletteType != PALETTE_NONE)
                {
                    uint32 reqPalItemCount = getD3DPaletteCount( platformTex->paletteType );

                    uint32 palDepth = Bitmap::getRasterFormatDepth( platformTex->rasterFormat );

                    assert( palDepth != 0 );

                    size_t paletteDataSize = getPaletteDataSize( reqPalItemCount, palDepth );

                    // Check whether we have palette data in the stream.
                    texNativeImageStruct.check_read_ahead( paletteDataSize );

                    void *palData = engineInterface->PixelAllocate( paletteDataSize );

                    try
                    {
	                    texNativeImageStruct.read( palData, paletteDataSize );
                    }
                    catch( ... )
                    {
                        engineInterface->PixelFree( palData );

                        throw;
                    }

                    // Store the palette.
                    platformTex->palette = palData;
                    platformTex->paletteSize = reqPalItemCount;
                }

                mipGenLevelGenerator mipLevelGen( metaHeader.width, metaHeader.height );

                if ( !mipLevelGen.isValidLevel() )
                {
                    throw RwException( "texture " + theTexture->GetName() + " has invalid dimensions" );
                }

                uint32 mipmapCount = 0;

                uint32 processedMipmapCount = 0;

                uint32 dxtCompression = platformTex->dxtCompression;

                bool hasDamagedMipmaps = false;

                for (uint32 i = 0; i < maybeMipmapCount; i++)
                {
                    bool couldEstablishLevel = true;

	                if (i > 0)
                    {
                        couldEstablishLevel = mipLevelGen.incrementLevel();
                    }

                    if (!couldEstablishLevel)
                    {
                        break;
                    }

                    // Create a new mipmap layer.
                    NativeTextureD3D8::mipmapLayer newLayer;

                    newLayer.layerWidth = mipLevelGen.getLevelWidth();
                    newLayer.layerHeight = mipLevelGen.getLevelHeight();

                    // Process dimensions.
                    uint32 texWidth = newLayer.layerWidth;
                    uint32 texHeight = newLayer.layerHeight;
                    {
		                // DXT compression works on 4x4 blocks,
		                // no smaller values allowed
		                if (dxtCompression != 0)
                        {
			                texWidth = ALIGN_SIZE( texWidth, 4u );
                            texHeight = ALIGN_SIZE( texHeight, 4u );
		                }
                    }

                    newLayer.width = texWidth;
                    newLayer.height = texHeight;

	                uint32 texDataSize = texNativeImageStruct.readUInt32();

                    // We started processing this mipmap.
                    processedMipmapCount++;

                    // Verify the data size.
                    bool isValidMipmap = true;
                    {
                        uint32 actualDataSize = 0;

                        if (dxtCompression != 0)
                        {
                            uint32 texItemCount = ( texWidth * texHeight );

                            actualDataSize = getDXTRasterDataSize(dxtCompression, texItemCount);
                        }
                        else
                        {
                            uint32 rowSize = getD3DRasterDataRowSize( texWidth, depth );

                            actualDataSize = getRasterDataSizeByRowSize( rowSize, texHeight );
                        }

                        if (actualDataSize != texDataSize)
                        {
                            isValidMipmap = false;
                        }
                    }

                    if ( !isValidMipmap )
                    {
                        // Even the Rockstar games texture generator appeared to have problems with mipmap generation.
                        // This is why textures appear to have the size of zero.

                        if (texDataSize != 0)
                        {
                            if ( !engineIgnoreSecureWarnings )
                            {
                               engineInterface->PushWarning( "texture " + theTexture->GetName() + " has damaged mipmaps (ignoring)" );
                            }

                            hasDamagedMipmaps = true;
                        }

                        // Skip the damaged bytes.
                        if (texDataSize != 0)
                        {
                            texNativeImageStruct.skip( texDataSize );
                        }
                        break;
                    }

                    // We first have to check whether there is enough data in the stream.
                    // Otherwise we would just flood the memory in case of an error;
                    // that could be abused by exploiters.
                    texNativeImageStruct.check_read_ahead( texDataSize );
                    
                    void *texelData = engineInterface->PixelAllocate( texDataSize );

                    try
                    {
	                    texNativeImageStruct.read( texelData, texDataSize );
                    }
                    catch( ... )
                    {
                        engineInterface->PixelFree( texelData );

                        throw;
                    }

                    // Store mipmap properties.
	                newLayer.dataSize = texDataSize;

                    // Store the image data pointer.
	                newLayer.texels = texelData;

                    // Put the layer.
                    platformTex->mipmaps.push_back( newLayer );

                    mipmapCount++;
                }
                
                if ( mipmapCount == 0 )
                {
                    throw RwException( "texture " + theTexture->GetName() + " is empty" );
                }

                // mipmapCount can only be smaller than maybeMipmapCount.
                // This is logically true and would be absurd to assert here.

                if ( processedMipmapCount < maybeMipmapCount )
                {
                    // Skip the remaining mipmaps (most likely zero-sized).
                    bool hasSkippedNonZeroSized = false;

                    for ( uint32 n = processedMipmapCount; n < maybeMipmapCount; n++ )
                    {
                        uint32 mipSize = texNativeImageStruct.readUInt32();

                        if ( mipSize != 0 )
                        {
                            hasSkippedNonZeroSized = true;

                            // Skip the section.
                            texNativeImageStruct.skip( mipSize );
                        }
                    }

                    if ( !engineIgnoreSecureWarnings && !hasDamagedMipmaps )
                    {
                        // Print the debug message.
                        if ( !hasSkippedNonZeroSized )
                        {
                            engineInterface->PushWarning( "texture " + theTexture->GetName() + " has zero sized mipmaps" );
                        }
                        else
                        {
                            engineInterface->PushWarning( "texture " + theTexture->GetName() + " violates mipmap rules" );
                        }
                    }
                }

                // Fix filtering mode.
                fixFilteringMode( *theTexture, mipmapCount );

                // - Verify auto mipmap
                {
                    bool hasAutoMipmaps = platformTex->autoMipmaps;

                    if ( hasAutoMipmaps )
                    {
                        bool canHaveAutoMipmaps = ( mipmapCount == 1 );

                        if ( !canHaveAutoMipmaps )
                        {
                            engineInterface->PushWarning( "texture " + theTexture->GetName() + " has an invalid auto-mipmap flag (fixing)" );

                            platformTex->autoMipmaps = false;
                        }
                    }
                }
            }
            else
            {
                engineInterface->PushWarning( "failed to find texture native image struct in D3D texture native" );
            }
        }
        catch( ... )
        {
            texNativeImageStruct.LeaveContext();

            throw;
        }

        texNativeImageStruct.LeaveContext();
    }

    // Read extensions.
    engineInterface->DeserializeExtensions( theTexture, inputProvider );
}

static PluginDependantStructRegister <d3d8NativeTextureTypeProvider, RwInterfaceFactory_t> d3dNativeTexturePluginRegister;

void registerD3D8NativePlugin( void )
{
    d3dNativeTexturePluginRegister.RegisterPlugin( engineFactory );
}

};