/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : DX8 Texture Manager * * * * $Archive:: /Commando/Code/ww3d2/textureloader.h $* * * * Original Author:: vss_sync * * * * Author : Kenny Mitchell * * * * $Modtime:: 06/27/02 1:27p $* * * * $Revision:: 2 $* * * * 06/27/02 KM Texture class abstraction * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifndef TEXTURELOADER_H #define TEXTURELOADER_H #if defined(_MSC_VER) #pragma once #endif #include "always.h" #include "texture.h" class StringClass; struct IDirect3DTexture8; class TextureLoadTaskClass; class TextureLoader { public: static void Init(void); static void Deinit(void); // Modify given texture size to nearest valid size on current hardware. static void Validate_Texture_Size(unsigned& width, unsigned& height, unsigned& depth); static IDirect3DTexture8 * Load_Thumbnail( const StringClass& filename,const Vector3& hsv_shift); // WW3DFormat texture_format); // Pass WW3D_FORMAT_UNKNOWN if you don't care static IDirect3DSurface8 * Load_Surface_Immediate( const StringClass& filename, WW3DFormat surface_format, // Pass WW3D_FORMAT_UNKNOWN if you don't care bool allow_compression); static void Request_Thumbnail(TextureBaseClass* tc); // Adds a loading task to the system. The task if processed in a separate // thread as soon as possible. The task will appear in finished tasks list // when it's been completed. The texture will be refreshed on the next // update call after appearing to the finished tasks list. static void Request_Background_Loading(TextureBaseClass* tc); // Textures can only be created and locked by the main thread so this function sends a request to the texture // handling system to load the texture immediatelly next time it enters the main thread. If this function // is called from the main thread the texture is loaded immediatelly. static void Request_Foreground_Loading(TextureBaseClass* tc); static void Flush_Pending_Load_Tasks(void); static void Update(void(*network_callback)(void) = NULL); // returns true if current thread of execution is allowed to make DX8 calls. static bool Is_DX8_Thread(void); static void Suspend_Texture_Load(); static void Continue_Texture_Load(); static void Set_Texture_Inactive_Override_Time(int time_ms) {TextureInactiveOverrideTime = time_ms;} private: static void Process_Foreground_Load (TextureLoadTaskClass *task); static void Process_Foreground_Thumbnail (TextureLoadTaskClass *task); static void Begin_Load_And_Queue (TextureLoadTaskClass *task); static void Load_Thumbnail (TextureBaseClass *tc); static bool TextureLoadSuspended; // The time in ms before a texture is thrown out. // The default is zero. The scripted movies set this to reduce texture stalls in movies. static int TextureInactiveOverrideTime; }; class TextureLoadTaskListNodeClass { friend class TextureLoadTaskListClass; public: TextureLoadTaskListNodeClass(void) : Next(0), Prev(0) { } TextureLoadTaskListClass *Get_List(void) { return List; } TextureLoadTaskListNodeClass *Next; TextureLoadTaskListNodeClass *Prev; TextureLoadTaskListClass * List; }; class TextureLoadTaskListClass { // This class implements an unsynchronized, double-linked list of TextureLoadTaskClass // objects, using an embedded list node. public: TextureLoadTaskListClass(void); // Returns true if list is empty, false otherwise. bool Is_Empty (void) const { return (Root.Next == &Root); } // Add a task to beginning of list void Push_Front (TextureLoadTaskClass *task); // Add a task to end of list void Push_Back (TextureLoadTaskClass *task); // Remove and return a task from beginning of list, or NULL if list is empty. TextureLoadTaskClass * Pop_Front (void); // Remove and return a task from end of list, or NULL if list is empty TextureLoadTaskClass * Pop_Back (void); // Remove specified task from list, if present void Remove (TextureLoadTaskClass *task); private: // This list is implemented using a sentinel node. TextureLoadTaskListNodeClass Root; }; class SynchronizedTextureLoadTaskListClass : public TextureLoadTaskListClass { // This class added thread-safety to the basic TextureLoadTaskListClass. public: SynchronizedTextureLoadTaskListClass(void); // See comments above for description of member functions. void Push_Front (TextureLoadTaskClass *task); void Push_Back (TextureLoadTaskClass *task); TextureLoadTaskClass * Pop_Front (void); TextureLoadTaskClass * Pop_Back (void); void Remove (TextureLoadTaskClass *task); private: FastCriticalSectionClass CriticalSection; }; /* ** (gth) The allocation system we're using for TextureLoadTaskClass has gotten a little ** complicated since Kenny added the new task types for Cube and Volume textures. The ** ::Destroy member is used to return a task to the pool now and must be over-ridden in ** each derived class to put the task back into the correct free list. */ class TextureLoadTaskClass : public TextureLoadTaskListNodeClass { public: enum TaskType { TASK_NONE, TASK_THUMBNAIL, TASK_LOAD, }; enum PriorityType { PRIORITY_LOW, PRIORITY_HIGH, }; enum StateType { STATE_NONE, STATE_LOAD_BEGUN, STATE_LOAD_MIPMAP, STATE_LOAD_COMPLETE, STATE_COMPLETE, }; TextureLoadTaskClass(void); ~TextureLoadTaskClass(void); static TextureLoadTaskClass * Create (TextureBaseClass *tc, TaskType type, PriorityType priority); static void Delete_Free_Pool (void); virtual void Destroy (void); virtual void Init (TextureBaseClass *tc, TaskType type, PriorityType priority); virtual void Deinit (void); TaskType Get_Type (void) const { return Type; } PriorityType Get_Priority (void) const { return Priority; } StateType Get_State (void) const { return State; } WW3DFormat Get_Format (void) const { return Format; } unsigned int Get_Width (void) const { return Width; } unsigned int Get_Height (void) const { return Height; } unsigned int Get_Mip_Level_Count (void) const { return MipLevelCount; } unsigned int Get_Reduction (void) const { return Reduction; } unsigned char * Get_Locked_Surface_Ptr (unsigned int level); unsigned int Get_Locked_Surface_Pitch(unsigned int level) const; TextureBaseClass * Peek_Texture (void) { return Texture; } IDirect3DTexture8 * Peek_D3D_Texture (void) { return (IDirect3DTexture8*)D3DTexture; } void Set_Type (TaskType t) { Type = t; } void Set_Priority (PriorityType p) { Priority = p; } void Set_State (StateType s) { State = s; } bool Begin_Load (void); bool Load (void); void End_Load (void); void Finish_Load (void); void Apply_Missing_Texture (void); protected: virtual bool Begin_Compressed_Load (void); virtual bool Begin_Uncompressed_Load (void); virtual bool Load_Compressed_Mipmap (void); virtual bool Load_Uncompressed_Mipmap(void); virtual void Lock_Surfaces (void); virtual void Unlock_Surfaces (void); void Apply (bool initialize); TextureBaseClass* Texture; IDirect3DBaseTexture8* D3DTexture; WW3DFormat Format; unsigned int Width; unsigned int Height; unsigned int MipLevelCount; unsigned int Reduction; Vector3 HSVShift; unsigned char * LockedSurfacePtr[MIP_LEVELS_MAX]; unsigned int LockedSurfacePitch[MIP_LEVELS_MAX]; TaskType Type; PriorityType Priority; StateType State; }; class CubeTextureLoadTaskClass : public TextureLoadTaskClass { public: CubeTextureLoadTaskClass(); virtual void Destroy (void); virtual void Init (TextureBaseClass *tc, TaskType type, PriorityType priority); virtual void Deinit (void); protected: virtual bool Begin_Compressed_Load (void); virtual bool Begin_Uncompressed_Load (void); virtual bool Load_Compressed_Mipmap (void); // virtual bool Load_Uncompressed_Mipmap(void); virtual void Lock_Surfaces (void); virtual void Unlock_Surfaces (void); private: unsigned char* Get_Locked_CubeMap_Surface_Pointer(unsigned int face, unsigned int level); unsigned int Get_Locked_CubeMap_Surface_Pitch(unsigned int face, unsigned int level) const; IDirect3DCubeTexture8* Peek_D3D_Cube_Texture(void) { return (IDirect3DCubeTexture8*)D3DTexture; } unsigned char* LockedCubeSurfacePtr[6][MIP_LEVELS_MAX]; unsigned int LockedCubeSurfacePitch[6][MIP_LEVELS_MAX]; }; class VolumeTextureLoadTaskClass : public TextureLoadTaskClass { public: VolumeTextureLoadTaskClass(); virtual void Destroy (void); virtual void Init (TextureBaseClass *tc, TaskType type, PriorityType priority); protected: virtual bool Begin_Compressed_Load (void); virtual bool Begin_Uncompressed_Load (void); virtual bool Load_Compressed_Mipmap (void); // virtual bool Load_Uncompressed_Mipmap(void); virtual void Lock_Surfaces (void); virtual void Unlock_Surfaces (void); private: unsigned char* Get_Locked_Volume_Pointer(unsigned int level); unsigned int Get_Locked_Volume_Row_Pitch(unsigned int level); unsigned int Get_Locked_Volume_Slice_Pitch(unsigned int level); IDirect3DVolumeTexture8* Peek_D3D_Volume_Texture(void) { return (IDirect3DVolumeTexture8*)D3DTexture; } unsigned int LockedSurfaceSlicePitch[MIP_LEVELS_MAX]; unsigned int Depth; }; #endif