JD2022-TU1/main/extern/gear4/eal/sources/ealdef.h

341 lines
20 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////////////////
//
/// \file ealdef.h Engine Abstraction Layer Reference API Definitions
//
// For any questions/feedback please email gearsupport@ubisoft.com.
//
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This file contains definitions used by all EAL API files.
//
// Look at the end of the file for documentation on the whole EAL API.
//
// “Simplicity is the ultimate sophistication” - Leonardo Da Vinci
//
////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __EALDEF_H_INCLUDED
#define __EALDEF_H_INCLUDED
/// This module covers the reference API definitions.
/*! \addtogroup EAL
@{
*/
/// EalDef file version. The Format is an integer value equal to Major.Minor multiplied by 100 (Version 2.10 = 210)
/// See "How to use the library" in the documentation below for more information.
#define EALDEF_VERSION 500
/// EAL_DLL_IMPLICIT must be defined by the client who requires an implicit and dynamic
/// DLL function linkage with the EAL implementation. Typically not for TG products.
#if !defined(EAL_DLL_ENTRY) && defined(EAL_DLL_IMPLICIT)
# if defined(EAL_DLL) || defined(EAL_IMPORT_DLL)
# if defined(_MSC_VER)
# define EAL_DLL_ENTRY __declspec(dllimport) // Microsoft
# endif
# else
# if defined(_MSC_VER)
# define EAL_DLL_ENTRY __declspec(dllexport) // Microsoft
# elif defined(_GCC)
# define EAL_DLL_ENTRY __attribute__((visibility("default"))) // GCC
# endif
# endif
#endif
#if !defined(EAL_DLL_ENTRY)
# define EAL_DLL_ENTRY // Using explicit linkage
#endif
/// EAL unique ID
typedef int eal_id; ///< EAL Id (tag) built with eal_constants values
/// List of EAL constants
enum eal_constants
{
EAL_ID_VOID = 0xFFFFFFFF, ///< Unassigned / void ID
EAL_ID_TYPE_MASK = 0xC0000000, ///< Mask - ID type
EAL_ID_OWNER_MASK = 0x3FF00000, ///< Mask - ID owner
EAL_ID_PRIVATE_MASK = 0x000FFFFF, ///< Mask - ID private section
EAL_ID_TYPE_SHIFT = 30, ///< Shift - ID type
EAL_ID_OWNER_SHIFT = 20, ///< Shift - ID owner
EAL_ID_PRIVATE_SHIFT = 0, ///< Shift - ID private section
EAL_ID_TYPE_ENGINE = (0 << EAL_ID_TYPE_SHIFT), ///< ID type for game engines
EAL_ID_TYPE_TG = (1 << EAL_ID_TYPE_SHIFT), ///< ID type for TG middlewares
EAL_ID_TYPE_THIRDPARTY = (2 << EAL_ID_TYPE_SHIFT), ///< ID type for 3th party products
EAL_ID_ENGINE_GENERIC = (EAL_ID_TYPE_ENGINE | (0 << EAL_ID_OWNER_SHIFT)), ///< Generic engine ID
EAL_ID_ENGINE_SCIMITAR = (EAL_ID_TYPE_ENGINE | (1 << EAL_ID_OWNER_SHIFT)), ///< Scimitar engine ID
EAL_ID_ENGINE_BLACKSMITH = (EAL_ID_TYPE_ENGINE | (2 << EAL_ID_OWNER_SHIFT)), ///< Blacksmith engine ID
EAL_ID_ENGINE_DUNIA = (EAL_ID_TYPE_ENGINE | (3 << EAL_ID_OWNER_SHIFT)), ///< Dunia engine ID
EAL_ID_ENGINE_YETI = (EAL_ID_TYPE_ENGINE | (4 << EAL_ID_OWNER_SHIFT)), ///< Yeti engine ID
EAL_ID_ENGINE_LYN = (EAL_ID_TYPE_ENGINE | (5 << EAL_ID_OWNER_SHIFT)), ///< LYN engine ID
EAL_ID_ENGINE_ONYX = (EAL_ID_TYPE_ENGINE | (6 << EAL_ID_OWNER_SHIFT)), ///< Onyx engine ID
EAL_ID_TG_GENERIC = (EAL_ID_TYPE_TG | ( 0 << EAL_ID_OWNER_SHIFT)), ///< Generic TG product ID
EAL_ID_TG_GEAR = (EAL_ID_TYPE_TG | ( 1 << EAL_ID_OWNER_SHIFT)), ///< TG Gear product ID
EAL_ID_TG_DARE = (EAL_ID_TYPE_TG | ( 2 << EAL_ID_OWNER_SHIFT)), ///< TG Dare product ID
EAL_ID_TG_FIRE = (EAL_ID_TYPE_TG | ( 3 << EAL_ID_OWNER_SHIFT)), ///< TG Fire product ID
EAL_ID_TG_REALTREE = (EAL_ID_TYPE_TG | ( 4 << EAL_ID_OWNER_SHIFT)), ///< TG RealTree product ID
EAL_ID_TG_REALBLAST = (EAL_ID_TYPE_TG | ( 5 << EAL_ID_OWNER_SHIFT)), ///< TG RealBlast product ID
EAL_ID_TG_OASIS = (EAL_ID_TYPE_TG | ( 6 << EAL_ID_OWNER_SHIFT)), ///< TG Oasis product ID
EAL_ID_TG_ANIMATION = (EAL_ID_TYPE_TG | ( 7 << EAL_ID_OWNER_SHIFT)), ///< TG Animation product ID
EAL_ID_TG_METRIX = (EAL_ID_TYPE_TG | ( 8 << EAL_ID_OWNER_SHIFT)), ///< TG Metrix product ID
EAL_ID_TG_ORBIT = (EAL_ID_TYPE_TG | ( 9 << EAL_ID_OWNER_SHIFT)), ///< TG Orbit product ID
EAL_ID_TG_PASSENGER = (EAL_ID_TYPE_TG | (10 << EAL_ID_OWNER_SHIFT)), ///< TG Passenger product ID
EAL_ID_TG_THEATER = (EAL_ID_TYPE_TG | (11 << EAL_ID_OWNER_SHIFT)), ///< TG Theater product ID
EAL_ID_TG_UBISERVICES = (EAL_ID_TYPE_TG | (12 << EAL_ID_OWNER_SHIFT)), ///< TG UbiServices product ID
EAL_ID_TG_GATOR = (EAL_ID_TYPE_TG | (13 << EAL_ID_OWNER_SHIFT)), ///< TG Gator product ID
EAL_ID_TG_NETZ = (EAL_ID_TYPE_TG | (14 << EAL_ID_OWNER_SHIFT)), ///< TG NetZ product ID
EAL_ID_TG_BLOOMBERG = (EAL_ID_TYPE_TG | (15 << EAL_ID_OWNER_SHIFT)), ///< TG Bloomberg product ID
EAL_ID_TG_PILOT = (EAL_ID_TYPE_TG | (16 << EAL_ID_OWNER_SHIFT)), ///< TG Pilot product ID
EAL_ID_TG_HERMES = (EAL_ID_TYPE_TG | (17 << EAL_ID_OWNER_SHIFT)), ///< TG Hermes product ID
EAL_ID_TG_ECHO = (EAL_ID_TYPE_TG | (18 << EAL_ID_OWNER_SHIFT)), ///< TG Echo product ID
EAL_ID_TG_MOTION = (EAL_ID_TYPE_TG | (19 << EAL_ID_OWNER_SHIFT)), ///< TG Motion product ID
EAL_ID_TG_EVIL = (EAL_ID_TYPE_TG | (20 << EAL_ID_OWNER_SHIFT)), ///< TG Evil product ID
EAL_ID_TG_RDV = (EAL_ID_TYPE_TG | (21 << EAL_ID_OWNER_SHIFT)), ///< TG Rendez Vous product ID
EAL_ID_TG_UPLAY = (EAL_ID_TYPE_TG | (22 << EAL_ID_OWNER_SHIFT)), ///< TG UPlay product ID
EAL_ID_TG_GRAFFITI = (EAL_ID_TYPE_TG | (23 << EAL_ID_OWNER_SHIFT)), ///< TG Graffiti product ID
EAL_ID_TG_PHOENIX = (EAL_ID_TYPE_TG | (24 << EAL_ID_OWNER_SHIFT)), ///< TG Phoenix product ID
EAL_ID_TG_SCRY = (EAL_ID_TYPE_TG | (25 << EAL_ID_OWNER_SHIFT)), ///< TG Scry product ID
EAL_ID_TG_ATOM = (EAL_ID_TYPE_TG | (26 << EAL_ID_OWNER_SHIFT)), ///< TG Atom product ID
EAL_ID_TG_TG2D = (EAL_ID_TYPE_TG | (27 << EAL_ID_OWNER_SHIFT)), ///< TG 2D-renderer product ID
EAL_ID_TG_FAPROFILER = (EAL_ID_TYPE_TG | (28 << EAL_ID_OWNER_SHIFT)), ///< TG Flying Architects Profiler product ID
EAL_ID_THIRDPARTY_GENERIC = (EAL_ID_TYPE_THIRDPARTY | (0 << EAL_ID_OWNER_SHIFT)), ///< Generic third party product ID
EAL_ID_THIRDPARTY_SDK = (EAL_ID_TYPE_THIRDPARTY | (1 << EAL_ID_OWNER_SHIFT)), ///< System SDK product ID
EAL_ID_THIRDPARTY_BINK = (EAL_ID_TYPE_THIRDPARTY | (2 << EAL_ID_OWNER_SHIFT)), ///< Bink product ID
EAL_ID_THIRDPARTY_HAVOK = (EAL_ID_TYPE_THIRDPARTY | (3 << EAL_ID_OWNER_SHIFT)) ///< Havok product ID
};
/// Timeout value in ms
enum eal_timeout
{
EAL_NO_WAIT = 0, ///< No timeout
EAL_INFINITE_WAIT = 0xffffffff ///< Wait forever
};
#include <cstddef>
#include <stdint.h> // All current toolchains provide <stdint.h> although some are not fully C99 compliant; <cstdint> requires C++11 support
#ifndef _MSC_VER
#define EAL_USE_STDINT_INT_TYPES
#endif //_MSC_VER
#ifdef EAL_USE_STDINT_INT_TYPES
// From <stdint.h>
typedef ::int8_t eal_s8; ///< 8-bit signed integer
typedef ::uint8_t eal_u8; ///< 8-bit unsigned integer
typedef ::int16_t eal_s16; ///< 16-bit signed integer
typedef ::uint16_t eal_u16; ///< 16-bit unsigned integer
typedef ::int32_t eal_s32; ///< 32-bit signed integer
typedef ::uint32_t eal_u32; ///< 32-bit unsigned integer
typedef ::int64_t eal_s64; ///< 64-bit signed integer
typedef ::uint64_t eal_u64; ///< 64-bit unsigned integer
#else
typedef signed char eal_s8; ///< 8-bit signed integer
typedef unsigned char eal_u8; ///< 8-bit unsigned integer
typedef signed short eal_s16; ///< 16-bit signed integer
typedef unsigned short eal_u16; ///< 16-bit unsigned integer
typedef signed long eal_s32; ///< 32-bit signed integer
typedef unsigned long eal_u32; ///< 32-bit unsigned integer
typedef signed long long eal_s64; ///< 64-bit signed integer
typedef unsigned long long eal_u64; ///< 64-bit unsigned integer
#endif //EAL_USE_STDINT_INT_TYPES
// From <cstddef>
typedef std::size_t eal_size_t; ///< Unsigned integer type of the result of the sizeof operator and the alignof operator (used for memory size parameters)
typedef std::ptrdiff_t eal_ptrdiff_t; ///< Signed integer type of the result of subtracting two pointers (used for memory offset parameters)
// From <stdint.h>
typedef ::intptr_t eal_intptr_t; ///< Signed integer type capable of holding a pointer
typedef ::uintptr_t eal_uintptr_t; ///< Unsigned integer type capable of holding a pointer
/*! @} */
/**
\page overview Overview
\brief The basics to know about the Engine Abstraction Layer.
- \subpage goals --- \copybrief goals
- \subpage contract --- \copybrief contract
- \subpage client --- \copybrief client
- \subpage dll --- \copybrief dll
- \subpage uuid --- \copybrief uuid
- \subpage supplier --- \copybrief supplier
- \subpage conventions --- \copybrief conventions
\page contract Contract Programming
\brief Brief overview of contract programming.
Design by Contract (DbC) or Programming by Contract is an approach to designing computer
software. It prescribes that software designers should define formal, precise, and verifiable
interface specifications for software components, which extend the ordinary definition of
abstract data types with preconditions, postconditions, and invariants. These specifications
are referred to as "contracts", in accordance with a conceptual metaphor with the conditions
and obligations of business contracts.
The term was coined by Bertrand Meyer in connection with his design of the Eiffel language.
Programming by contract creates a contract between the software developer and software user -
in Meyer's terms the supplier and the client. Every feature, or method, starts with a
precondition that must be satisfied by the client of the routine. And each feature ends with
postconditions which the supplier guarantees to be true (if and only if the preconditions
were met).
\page goals Design Goals & Philosophy
\brief Description of the design goals of the library.
- The first goal of the EAL is to provide a standard connection point between middleware and
the game engine. EAL covers the majority of services that are typically managed by the game
engine but needed by middleware, such as file access, memory allocation, logging, and so on.\n
Included in this goal is the desire to be able to connect any mix of targets (debug/retail/etc.)
- The second goal is to create an API that offers the lowest level of services that cover the
common denominator between all engines. This also ensures minimal work for supplying an EAL
for any engine. It is expected that a client will create a more user-friendly layer on top of
EAL.
- The third goal is to ensure that the client provides to the engine a rich set of
information when calling a function. This helps in two ways: first, it helps improve global
automated management of resources such as memory and CPU; second, this information can also
be routed to tools. The best example of this concept is the inclusion of tags for almost every
resource used in the EAL API. With tags, the implementation can always identify which
middleware is requesting the resource. This can be used, for example, to keep track of all the
memory used by <a HREF="http://dare" target="_blank">Dare</a>. It can also be used, for example, to ensure all
jobs created for <a HREF="http://fire" target="_blank">Fire</a> are running on a specific core.
\page client How to use the library
\brief Description of how to use the EAL library.
- You must always call \c EalxxxLibInit() before calling any other function in the library
(exception made in DLLs), where \c xxx represents the API (Mem, File, Log, and so on).
If your call to the initialization function fails, it probably means that the supplier does
NOT support the EAL API version you are using.
If the client supports a higher version than you are using it will work.
- EAL is backward compatible up to 3 Major versions. Normally, a supplier is expected to provide
support for the last 3 Major versions. Minor versions cannot change the interface, they are
mostly documentation changes.
- You are allowed to call the initialization function as many times as you want.
You should call the same number of shutdowns upon exiting.
- All calls are thread-safe
- We recommend using EAL IDs all the time, even in retail, since they have a minimum weight of
32 bits, yet can still be VERY useful to find problems in retail versions.
- The term 'NULL' used in comments literally means '0'.
- The term 'static' in parameter comments refers to variables that stay at the same memory
location for the whole duration of the program execution. It allows EAL providers to not copy
the data and simply keep a pointer or reference to the parameter. The typical case is for
debug strings.
- The term 'valid' in parameter comments means data properly allocated and initialized. In the
case of pointers, NULL is not accepted.
\page supplier How to supply an EAL implementation
\brief Information on how to supply (implement) EAL services in an engine.
- Be sure to count the number of times the initialization function is called. Only uninitialize
when count of calls to Shutdown() is the same.
- In your implementation of an EAL library, it may happen that you have circular dependencies
between two modules. A typical case is memory and performance logging: the module must have a
"2-step" initialization. For the first part you initialize the internals of your library, so
it is ready to accept calls to its API. Then, for the second part, you initialize sub EAL
modules. See example code below.
- You must implement the whole interface, including debug functions, even if you are compiling
in retail. At some point, you may end up linking a library compiled in debug or release with
your retail engine for debugging a specific problem.
- The whole API can be called by many different middlewares in different thread contexts.
So, all your API should be thread-safe (including the initialization function calls).
\page dll Using EAL in a DLL
\brief Information on how to use EAL inside a DLL.
If you are writing code that is using EAL and that will be in a separate DLL, you will need to
do the following:
- Include in your DLL project all the \em ealxxxdll.cpp files corresponding to the services you are
using.
- Define \c EAL_IMPORT_DLL in your project.
\deprecated EAL_DLL is DEPRECATED since version 4.00. Please use EAL_IMPORT_DLL instead.
EAL_DLL will be removed in version 7.00.
- Create a DLL initialization function that gets EAL interfaces (\c eal_xxx_dll_interface) as
found in \em ealxxx.h.
- Call the \c EalxxDllInitInterface() with that interface.
- Call the EAL functions as usual in your code, including a call to \c EalxxxLibInit().
On the engine side:
- Include in your project the files \em ealxxxdll.cpp corresponding to the services you are
using.
- Call \c EalxxxDllPopulateInterface() to populate an interface (\c eal_xxx_dll_interface).
- Initiate the DLL and provide the interfaces.
How does it work?
Really simple. On the DLL side, \em ealxxxdll.cpp contains a global variable of type
\c eal_xxx_dll_interface. This variable contains a function pointer to all EAL functions.
When you call \c EalxxxDllInitInterface(), all function pointers are initalized.
The DLL side also contains code for every EAL function, which simply redirects the call to the
function pointer.
The code on the engine side (\c EalxxxDllPopulateInterface) simply fills up the interface
with the address of all the supplied EAL functions.
\page uuid EAL IDs
\brief Description of the EAL Identifier System used through the EAL API.
EAL IDs are used to identify values for a specific Ubisoft product or engine.
These IDs, used for all APIs that require tags (such as \c EalMem, \c EalJob, and others),
serve many purposes. They provide detailed information regarding the origin of the
calls made to EAL, allowing the implementers to perform specific actions in some cases.
They are also very valuable for debugging and logging tools.
Note that each API that requires EAL IDs does not share the tags. This means value can
overlap. For example, it is ok to use exactly the same value for a tag in a memory library
and the performance track ID because they are used in totally different contexts (APIs).
\par TAG Format
- <b>Bits 30-31</b>: Used to identify the type of product (range 0-3).
- \c 0x00 --- Game Engine
- \c 0x01 --- Ubisoft internal TG product (or other internal middleware)
- \c 0x02 --- Third-party middleware (such as Bink)
- \c 0x03 --- Reserved for future use
- <b>Bits 20-29</b>: Used to identify the product/engine/third-party. The IDs are attributed by the TG.
If your engine/product/third-party product is not on the list, please contact the TG at
<a href="mailto:gearsupport@ubisoft.com?subject=Need an ID">gearsupport@ubisoft.com</a> to get an ID.
- <b>Bits 0-19</b>: Free to use by the owner. The owner is responsible for managing these bits.
ID examples:
\code
#define FIRE_MEM_VERTEX_BUFFER (EAL_ID_TG_FIRE | 0x00000001)
#define FIRE_MEM_TEXTURE (EAL_ID_TG_FIRE | 0x00000002)
#define FIRE_MEM_AC_BINARY (EAL_ID_TG_FIRE | 0x00000003)
And so on.
\endcode
\page conventions Library Conventions
\brief Programming convention to use for anyone expanding the EAL.
This section is dedicated to people who would like to extend the EAL library.
- Line length should not exceed 100 characters.
- All filenames are in lower case.
- Do not use default parameters in EAL functions. The only exception to this rule is the
initialization function because we need the version the client is using.
- Do not change an existing define/enum value. You can only add new ones.
- All functions must be implemented in all targets (retail/release/debug). It is possible with
EAL to use a debug version of a middleware, even though the engine is compiled in release or
retail. In that case, you will need to link with the debug version of the functions.
- The version of the library is included in the initialization function.
- Backward compatibility is preserved for 3 versions, hence any function that is declared
deprecated must stay for 3 versions. After 3 versions, it can be removed.
- You CANNOT remove any entry in the DLL interface structure. Deprecated function entries can
be recycled 3 versions after they were declared deprecated, but they can never be removed.
- When adding new middleware, engines, and so on, a new version is not mandatory. The essential
is that the value used is unique and reserved by the EAL team.
- Each API is independent (such as ealmem and ealfile). Their version can evolve at different
paces, hence they may be of a different version.
- In order to deprecate a function, you simply need to add the Doxygen deprecated keyword in
front of the function comment with the version number in which it became deprecated.
The function must remain in the library as a deprecated one for at least 3 versions before
being removed.
**/
#endif // #ifndef __EALDEF_H_INCLUDED