#include "pch.hpp"
//===========================================================================//
// File:	 Texture API.cpp												 //
// Project:  GameOS					                                         //
// Contents: Texture Management API (client-visible)						 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 04/03/00  NK     Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 2000 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "Texture Manager.hpp"

// Functions defined below:
DWORD __stdcall gos_NewTextureFromMemory( gos_TextureFormat Format, const char* Name, BYTE* pBitmap, DWORD SizeBytes, DWORD Hints, gos_RebuildFunction pFunc, void *pInstance );
DWORD __stdcall gos_NewEmptyTexture( gos_TextureFormat Format, const char* Name, DWORD HeightWidth, DWORD Hints, gos_RebuildFunction pFunc, void *pInstance );
DWORD __stdcall gos_NewTextureFromFile( gos_TextureFormat Format, const char* FileName, DWORD Hints, gos_RebuildFunction pFunc, void *pInstance );
void __stdcall gos_UnLockTexture( DWORD Handle );
void __stdcall gos_LockTexture( DWORD Handle, DWORD MipMapWidth, bool ReadOnly, TEXTUREPTR* TextureInfo );
void __stdcall gos_DestroyTexture( DWORD Handle );
void __stdcall gos_PreloadTexture( DWORD Handle );
const char* __stdcall gos_GetTextureName( DWORD Handle );
void __stdcall gos_SetTextureName( DWORD Handle, const char *name );
bool __stdcall gos_RecreateTextureHeaps();
void __stdcall gos_ConvertTextureRect( DWORD Handle, DWORD DestLeft, DWORD DestTop, DWORD *Source, DWORD SourcePitch, DWORD Width, DWORD Height );

extern DWORD RenderStates[gos_MaxState];			// Current User settings
void FlushRenderStates();

DWORD CTexInfo::TexturePointerToHandle()
{
	DWORD Handle = ( (DWORD)this - (DWORD)TexInfo ) / sizeof(TexInfo[0]);
	Handle++;
	if( ( Handle < 1 ) || ( Handle > 1023 ) )
		STOP(("Invalid handle"));
	return Handle;
}

CTexInfo * CTexInfo::TextureHandleToPtr( DWORD Handle )
{
	if( ( Handle < 1 ) || ( Handle > 1023 ) )
		STOP(("Invalid handle"));
	Handle--;
	CTexInfo *ptr = &TexInfo[Handle];
	return ptr;
}



DWORD __stdcall gos_NewTextureFromMemory( gos_TextureFormat Format, const char* Name, BYTE* pBitmap, DWORD SizeBytes, DWORD Hints, gos_RebuildFunction pFunc, void *pInstance )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_NewTextureFromMemory");
	SPEW(( GROUP_TEXTURE, "gos_NewTextureFromMemory(\"%s\")",Name ));

	gosASSERT( pBitmap && SizeBytes && !(Hints&(gosHint_ReloadFromDisk|gosHint_UserMipMaps)) );

	CTexInfo *pTexInfo = CTexInfo::Allocate();

	pTexInfo->Initialize( Format, Name, pBitmap, SizeBytes, 0, 0, Hints, pFunc, pInstance );

	return TEXPTR_TO_HANDLE( pTexInfo );
}

DWORD __stdcall gos_NewEmptyTexture( gos_TextureFormat Format, const char* Name, DWORD HeightWidth, DWORD Hints, gos_RebuildFunction pFunc, void *pInstance )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_NewEmptyTexture");
	SPEW(( GROUP_TEXTURE, "gos_NewEmptyTexture(\"%s\")",Name ));

	WORD Width = (WORD)(HeightWidth & 0x0000ffff);
	WORD Height = WORD(HeightWidth >> 16);
	if( !Height )
		Height = Width;

	gosASSERT( Width && !(Hints&gosHint_ReloadFromDisk) && (Format != gos_Texture_Detect) );

	CTexInfo *pTexInfo = CTexInfo::Allocate();

	pTexInfo->Initialize( Format, Name, 0, 0, Width, Height, Hints, pFunc, pInstance );

	return TEXPTR_TO_HANDLE( pTexInfo );
}

DWORD __stdcall gos_NewTextureFromFile( gos_TextureFormat Format, const char* FileName, DWORD Hints, gos_RebuildFunction pFunc, void *pInstance )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_NewTextureFromFile");
	SPEW(( GROUP_TEXTURE, "gos_NewTextureFromFile(\"%s\")",FileName ));

	if( strlen( FileName ) < 5 )
	{
		STOP(( "Invalid texture file name %s", FileName ));
	}

	CTexInfo *pTexInfo = CTexInfo::Allocate();

	pTexInfo->Initialize( Format, FileName, 0, 0, 0, 0, Hints, pFunc, pInstance );

	return TEXPTR_TO_HANDLE( pTexInfo );
}

void __stdcall gos_UnLockTexture( DWORD Handle )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_UnLockTexture");
	SPEW(( GROUP_TEXTURE, "gos_UnLockTexture(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
		STOP(( "Invalid texture unlocked (0x%x)",Handle ));
	if( !pTexInfo->IsLocked() )
		STOP(( "Texture (0x%x) was not locked!" ));

	pTexInfo->Unlock();
}

void __stdcall gos_LockTexture( DWORD Handle, DWORD MipMapWidth, bool ReadOnly, TEXTUREPTR* TextureInfo )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_LockTexture");
	SPEW(( GROUP_TEXTURE, "gos_LockTexture(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
		STOP(( "Invalid texture locked (0x%x)",Handle ));
	if( pTexInfo->CanRebuild() )
		STOP(( "Can't lock a texture with a rebuild function... more than once" ));
	if( MipMapWidth > pTexInfo->Width() )
		STOP(( "Trying to lock a mipmap wider than the texture" ));
	if( MipMapWidth && !(pTexInfo->Hints() & gosHint_UserMipMaps) )
		STOP(( "Lock mipmap only works on gosHint_UserMipMaps textures" ));
	if( pTexInfo->Hints() & gosHint_ReloadFromDisk )
		STOP(( "Lock mipmap cannot be used on ReloadfromDisk textures" ));
	if( pTexInfo->IsLocked() )
		STOP(( "Cannot nest texture locks" ));

	pTexInfo->Lock( MipMapWidth, ReadOnly, TextureInfo );
}

void __stdcall gos_DestroyTexture( DWORD Handle )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_DestroyTexture");
	SPEW(( GROUP_TEXTURE, "gos_DestroyTexture(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
	{
		if( !CTexInfo::ManagerInitialized() )
			return;
		STOP(( "Invalid texture destroyed (0x%x)",Handle ));
	}

	pTexInfo->Free();
}

void __stdcall gos_PreloadTexture( DWORD Handle )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_PreloadTexture");
	SPEW(( GROUP_TEXTURE, "gos_PreloadTexture(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
		STOP(( "Invalid texture preloaded (0x%x)",Handle ));

	pTexInfo->SetPreload();
}

const char* __stdcall gos_GetTextureName( DWORD Handle )
{
	SPEW(( GROUP_TEXTURE, "gos_GetTextureName(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
		STOP(( "Getname on invalid texture (0x%x)",Handle ));

	return pTexInfo->Name();
}

void __stdcall gos_SetTextureName( DWORD Handle, const char *name )
{
	SPEW(( GROUP_TEXTURE, "gos_SetTextureName(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
		STOP(( "Setname on invalid texture (0x%x)",Handle ));

	if( name && strlen(name)<MAX_PATH ) 
		pTexInfo->SetName(name);
	else
		pTexInfo->SetName("Unnamed texture");
}

bool __stdcall gos_RecreateTextureHeaps()
{
	SPEW(( GROUP_TEXTURE, "Gos3D::TextureAPI::gos_RecreateTextureHeaps" ));

	return CTexInfo::RecreateHeaps();
}

void __stdcall gos_ConvertTextureRect( DWORD Handle, DWORD DestLeft, DWORD DestTop, DWORD *Source, DWORD SourcePitch, DWORD Width, DWORD Height )
{
	LOG_BLOCK("Gos3D::TextureAPI::gos_ConvertTextureRect");
	SPEW(( GROUP_TEXTURE, "gos_ConvertTextureRect(0x%x)",Handle ));

	CTexInfo *pTexInfo = TEXHANDLE_TO_PTR(Handle);

	if( !pTexInfo->ValidTexture() )
		STOP(( "ConvertTextureRect on invalid texture (0x%x)",Handle ));

	pTexInfo->UpdateRect( DestLeft, DestTop, Source, SourcePitch, Width, Height );
}
