mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-12-13 22:01:25 +00:00
Merge remote-tracking branch 'origin/master' into polybackend
This commit is contained in:
commit
bb47230f79
126 changed files with 2186 additions and 1293 deletions
|
@ -6,37 +6,23 @@ branches:
|
||||||
|
|
||||||
clone_depth: 10
|
clone_depth: 10
|
||||||
|
|
||||||
|
image:
|
||||||
|
- Visual Studio 2019
|
||||||
|
- Visual Studio 2015
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- GENERATOR: "Visual Studio 14 2015"
|
- ARCH: x64
|
||||||
CONFIGURATION: Release
|
- ARCH: Win32
|
||||||
TOOLSET: v140_xp
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
|
|
||||||
- GENERATOR: "Visual Studio 14 2015 Win64"
|
|
||||||
CONFIGURATION: Release
|
|
||||||
TOOLSET: v140
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
|
|
||||||
- GENERATOR: "Visual Studio 15 2017"
|
|
||||||
CONFIGURATION: Release
|
|
||||||
TOOLSET: v141_xp
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
|
|
||||||
- GENERATOR: "Visual Studio 15 2017 Win64"
|
|
||||||
CONFIGURATION: Release
|
|
||||||
TOOLSET: v141
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
|
|
||||||
- GENERATOR: "Visual Studio 15 2017 Win64"
|
|
||||||
CONFIGURATION: Debug
|
|
||||||
TOOLSET: v141
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
|
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- md build
|
- md build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake -G "%GENERATOR%" -T "%TOOLSET%" -DPK3_QUIET_ZIPDIR=YES ..
|
- cmake -A %ARCH% -DPK3_QUIET_ZIPDIR=YES ..
|
||||||
- cmake --build . --config "%CONFIGURATION%" -- -maxcpucount -verbosity:minimal
|
- cmake --build . --config Release -- -maxcpucount -verbosity:minimal
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
- set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%\
|
- set OUTPUT_DIR=%APPVEYOR_BUILD_FOLDER%\build\Release\
|
||||||
- 7z a ..\gzdoom.zip "%OUTPUT_DIR%gzdoom.exe" "%OUTPUT_DIR%*.pk3"
|
- 7z a ..\gzdoom.zip "%OUTPUT_DIR%gzdoom.exe" "%OUTPUT_DIR%*.pk3"
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -24,3 +24,4 @@
|
||||||
/build_vc2017-32
|
/build_vc2017-32
|
||||||
/build2
|
/build2
|
||||||
/build_vc2019-64
|
/build_vc2019-64
|
||||||
|
/build_vc2019-32
|
||||||
|
|
|
@ -239,7 +239,21 @@ else()
|
||||||
else()
|
else()
|
||||||
set( ALL_C_FLAGS "-ffp-contract=off" )
|
set( ALL_C_FLAGS "-ffp-contract=off" )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if ( UNIX )
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
check_symbol_exists( "fts_set" "fts.h" HAVE_FTS )
|
||||||
|
if ( NOT HAVE_FTS )
|
||||||
|
include ( FindPkgConfig )
|
||||||
|
pkg_check_modules( MUSL_FTS musl-fts )
|
||||||
|
if ( MUSL_FTS_FOUND )
|
||||||
|
set ( ALL_C_FLAGS "${ALL_C_FLAGS} ${MUSL_FTS_LDFLAGS}" )
|
||||||
|
else ( MUSL_FTS_FOUND )
|
||||||
|
message (ERROR "fts_* functions not found in the system" )
|
||||||
|
endif ( MUSL_FTS_FOUND )
|
||||||
|
endif ( NOT HAVE_FTS )
|
||||||
|
endif ( UNIX )
|
||||||
|
|
||||||
set( REL_C_FLAGS "" )
|
set( REL_C_FLAGS "" )
|
||||||
set( DEB_C_FLAGS "" )
|
set( DEB_C_FLAGS "" )
|
||||||
|
|
||||||
|
@ -310,6 +324,19 @@ else()
|
||||||
set( ZLIB_LIBRARY z )
|
set( ZLIB_LIBRARY z )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if( HAVE_VM_JIT AND UNIX )
|
||||||
|
check_symbol_exists( "backtrace" "execinfo.h" HAVE_BACKTRACE )
|
||||||
|
if( NOT HAVE_BACKTRACE )
|
||||||
|
set( CMAKE_REQUIRED_FLAGS "-lexecinfo" )
|
||||||
|
check_symbol_exists( "backtrace" "execinfo.h" HAVE_LIBEXECINFO )
|
||||||
|
if( HAVE_LIBEXECINFO )
|
||||||
|
set( ALL_C_FLAGS "${ALL_C_FLAGS} -lexecinfo" )
|
||||||
|
else( HAVE_LIBEXECINFO )
|
||||||
|
set( HAVE_VM_JIT NO )
|
||||||
|
endif( HAVE_LIBEXECINFO )
|
||||||
|
endif( NOT HAVE_BACKTRACE )
|
||||||
|
endif( HAVE_VM_JIT AND UNIX )
|
||||||
|
|
||||||
if( ${HAVE_VM_JIT} )
|
if( ${HAVE_VM_JIT} )
|
||||||
if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT )
|
if( ASMJIT_FOUND AND NOT FORCE_INTERNAL_ASMJIT )
|
||||||
message( STATUS "Using system asmjit, includes found at ${ASMJIT_INCLUDE_DIR}" )
|
message( STATUS "Using system asmjit, includes found at ${ASMJIT_INCLUDE_DIR}" )
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
Some software in this archive may be from the book _Methods and
|
|
||||||
Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
|
|
||||||
International, 1989) or from the Cephes Mathematical Library, a
|
|
||||||
commercial product. In either event, it is copyrighted by the author.
|
|
||||||
What you see here may be used freely but it comes with no support or
|
|
||||||
guarantee.
|
|
||||||
|
|
||||||
Stephen L. Moshier
|
|
||||||
moshier@na-net.ornl.gov
|
|
||||||
|
|
|
@ -1291,6 +1291,7 @@ set (PCH_SOURCES
|
||||||
utility/nodebuilder/nodebuild_utility.cpp
|
utility/nodebuilder/nodebuild_utility.cpp
|
||||||
utility/sc_man.cpp
|
utility/sc_man.cpp
|
||||||
utility/stats.cpp
|
utility/stats.cpp
|
||||||
|
utility/atterm.cpp
|
||||||
utility/cmdlib.cpp
|
utility/cmdlib.cpp
|
||||||
utility/colormatcher.cpp
|
utility/colormatcher.cpp
|
||||||
utility/configfile.cpp
|
utility/configfile.cpp
|
||||||
|
@ -1451,10 +1452,9 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||||
# Need to enable intrinsics for these files.
|
# Need to enable intrinsics for these files.
|
||||||
if( SSE_MATTERS )
|
if( SSE_MATTERS )
|
||||||
set_source_files_properties(
|
set_source_files_properties(
|
||||||
gl/system/gl_swframebuffer.cpp
|
rendering/polyrenderer/poly_all.cpp
|
||||||
polyrenderer/poly_all.cpp
|
rendering/swrenderer/r_all.cpp
|
||||||
swrenderer/r_all.cpp
|
utility/x86.cpp
|
||||||
x86.cpp
|
|
||||||
PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
|
PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -74,7 +74,7 @@ extern bool insave;
|
||||||
|
|
||||||
CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH)
|
CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH)
|
||||||
CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO)
|
CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO)
|
||||||
CVAR (Bool, cl_blockcheats, false, 0)
|
CVAR (Int, cl_blockcheats, 0, 0)
|
||||||
|
|
||||||
CCMD (toggleconsole)
|
CCMD (toggleconsole)
|
||||||
{
|
{
|
||||||
|
@ -88,9 +88,9 @@ bool CheckCheatmode (bool printmsg)
|
||||||
if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
|
if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (cl_blockcheats)
|
else if (cl_blockcheats != 0)
|
||||||
{
|
{
|
||||||
if (printmsg) Printf ("cl_blockcheats is turned on and disabled this command.\n");
|
if (printmsg && cl_blockcheats == 1) Printf ("cl_blockcheats is turned on and disabled this command.\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -123,6 +123,8 @@ void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth)
|
||||||
{
|
{
|
||||||
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
|
if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared)
|
||||||
{
|
{
|
||||||
|
if (mBufferWasCleared)
|
||||||
|
mLastLineNeedsUpdate = false;
|
||||||
m_BrokenConsoleText.Clear();
|
m_BrokenConsoleText.Clear();
|
||||||
mBrokenStart.Clear();
|
mBrokenStart.Clear();
|
||||||
mBrokenStart.Push(0);
|
mBrokenStart.Push(0);
|
||||||
|
|
|
@ -102,6 +102,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "g_cvars.h"
|
#include "g_cvars.h"
|
||||||
#include "r_data/r_vanillatrans.h"
|
#include "r_data/r_vanillatrans.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, hud_althud)
|
EXTERN_CVAR(Bool, hud_althud)
|
||||||
EXTERN_CVAR(Int, vr_mode)
|
EXTERN_CVAR(Int, vr_mode)
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "scriptutil.h"
|
#include "scriptutil.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,11 @@ inline float DEG2RAD(float deg)
|
||||||
return deg * float(M_PI / 180.0);
|
return deg * float(M_PI / 180.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double DEG2RAD(double deg)
|
||||||
|
{
|
||||||
|
return deg * (M_PI / 180.0);
|
||||||
|
}
|
||||||
|
|
||||||
inline float RAD2DEG(float deg)
|
inline float RAD2DEG(float deg)
|
||||||
{
|
{
|
||||||
return deg * float(180. / M_PI);
|
return deg * float(180. / M_PI);
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
|
#define ARTIFLASH_OFFSET (statusBar->invBarOffset+6)
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -802,7 +802,9 @@ void DBaseStatusBar::CallTick()
|
||||||
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
|
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
|
||||||
{
|
{
|
||||||
DHUDMessageBase *old = NULL;
|
DHUDMessageBase *old = NULL;
|
||||||
TObjPtr<DHUDMessageBase *>*prev;
|
DObject* pointing;
|
||||||
|
TObjPtr<DHUDMessageBase *>*prevp;
|
||||||
|
DHUDMessageBase* prev;
|
||||||
|
|
||||||
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
|
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
|
||||||
if (old != NULL)
|
if (old != NULL)
|
||||||
|
@ -816,20 +818,25 @@ void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer
|
||||||
layer = HUDMSGLayer_Default;
|
layer = HUDMSGLayer_Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = &Messages[layer];
|
pointing = this;
|
||||||
|
prevp = &Messages[layer];
|
||||||
|
prev = *prevp;
|
||||||
|
|
||||||
// The ID serves as a priority, where lower numbers appear in front of
|
// The ID serves as a priority, where lower numbers appear in front of
|
||||||
// higher numbers. (i.e. The list is sorted in descending order, since
|
// higher numbers. (i.e. The list is sorted in descending order, since
|
||||||
// it gets drawn back to front.)
|
// it gets drawn back to front.)
|
||||||
while (*prev != NULL && (*prev)->SBarID > id)
|
while (prev != NULL && prev->SBarID > id)
|
||||||
{
|
{
|
||||||
prev = &(*prev)->Next;
|
pointing = prev;
|
||||||
|
prevp = &prev->Next;
|
||||||
|
prev = *prevp;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->Next = *prev;
|
msg->Next = prev;
|
||||||
msg->SBarID = id;
|
msg->SBarID = id;
|
||||||
*prev = msg;
|
*prevp = msg;
|
||||||
GC::WriteBarrier(msg);
|
GC::WriteBarrier(msg, prev);
|
||||||
|
GC::WriteBarrier(pointing, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -843,15 +850,18 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg)
|
||||||
for (size_t i = 0; i < countof(Messages); ++i)
|
for (size_t i = 0; i < countof(Messages); ++i)
|
||||||
{
|
{
|
||||||
DHUDMessageBase *probe = Messages[i];
|
DHUDMessageBase *probe = Messages[i];
|
||||||
|
DObject* pointing = this;
|
||||||
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
||||||
|
|
||||||
while (probe && probe != msg)
|
while (probe && probe != msg)
|
||||||
{
|
{
|
||||||
|
pointing = probe;
|
||||||
prev = &probe->Next;
|
prev = &probe->Next;
|
||||||
probe = probe->Next;
|
probe = probe->Next;
|
||||||
}
|
}
|
||||||
if (probe != NULL)
|
if (probe != NULL)
|
||||||
{
|
{
|
||||||
|
GC::WriteBarrier(pointing, probe->Next);
|
||||||
*prev = probe->Next;
|
*prev = probe->Next;
|
||||||
probe->Next = nullptr;
|
probe->Next = nullptr;
|
||||||
return probe;
|
return probe;
|
||||||
|
@ -864,16 +874,19 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < countof(Messages); ++i)
|
for (size_t i = 0; i < countof(Messages); ++i)
|
||||||
{
|
{
|
||||||
|
DObject* pointing = this;
|
||||||
DHUDMessageBase *probe = Messages[i];
|
DHUDMessageBase *probe = Messages[i];
|
||||||
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
||||||
|
|
||||||
while (probe && probe->SBarID != id)
|
while (probe && probe->SBarID != id)
|
||||||
{
|
{
|
||||||
|
pointing = probe;
|
||||||
prev = &probe->Next;
|
prev = &probe->Next;
|
||||||
probe = probe->Next;
|
probe = probe->Next;
|
||||||
}
|
}
|
||||||
if (probe != NULL)
|
if (probe != NULL)
|
||||||
{
|
{
|
||||||
|
GC::WriteBarrier(pointing, probe->Next);
|
||||||
*prev = probe->Next;
|
*prev = probe->Next;
|
||||||
probe->Next = nullptr;
|
probe->Next = nullptr;
|
||||||
return probe;
|
return probe;
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
static TArray<cluster_info_t> wadclusterinfos;
|
static TArray<cluster_info_t> wadclusterinfos;
|
||||||
TArray<level_info_t> wadlevelinfos;
|
TArray<level_info_t> wadlevelinfos;
|
||||||
|
|
|
@ -49,7 +49,7 @@ static void SetDoom2Wad()
|
||||||
{
|
{
|
||||||
if (Doom2Wad == -1)
|
if (Doom2Wad == -1)
|
||||||
{
|
{
|
||||||
FString iwad = Wads.GetWadFullName(1);
|
FString iwad = Wads.GetWadFullName(Wads.GetIwadNum());
|
||||||
iwad.ToLower();
|
iwad.ToLower();
|
||||||
if (iwad.IndexOf("plutonia") >= 0) Doom2Wad = 1;
|
if (iwad.IndexOf("plutonia") >= 0) Doom2Wad = 1;
|
||||||
else if (iwad.IndexOf("tnt") >= 0) Doom2Wad = 2;
|
else if (iwad.IndexOf("tnt") >= 0) Doom2Wad = 2;
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#include "st_start.h"
|
#include "st_start.h"
|
||||||
#include "m_misc.h"
|
#include "m_misc.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
#include "i_net.h"
|
#include "i_net.h"
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
|
|
||||||
#include "gameconfigfile.h"
|
#include "gameconfigfile.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
FGameConfigFile *GameConfig;
|
FGameConfigFile *GameConfig;
|
||||||
|
|
||||||
|
|
|
@ -767,6 +767,11 @@ bool MapLoader::LoadExtendedNodes (FileReader &dalump, uint32_t id)
|
||||||
|
|
||||||
static bool P_CheckV4Nodes(MapData *map)
|
static bool P_CheckV4Nodes(MapData *map)
|
||||||
{
|
{
|
||||||
|
if (map->Size(ML_NODES) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char header[8];
|
char header[8];
|
||||||
|
|
||||||
map->Read(ML_NODES, header, 8);
|
map->Read(ML_NODES, header, 8);
|
||||||
|
|
|
@ -510,8 +510,6 @@ void MapLoader::ParseReplies (const char *name, int pos, FStrifeDialogueReply **
|
||||||
{
|
{
|
||||||
FStringf label("$TXT_RPLY%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Reply).GetChars());
|
FStringf label("$TXT_RPLY%d_%s_d%d_%s", j, name, pos, TokenFromString(rsp->Reply).GetChars());
|
||||||
reply->Reply = GStrings.exists(label.GetChars() + 1)? label : FString(rsp->Reply);
|
reply->Reply = GStrings.exists(label.GetChars() + 1)? label : FString(rsp->Reply);
|
||||||
|
|
||||||
reply->Reply = label;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "teaminfo.h"
|
#include "teaminfo.h"
|
||||||
#include "r_data/sprites.h"
|
#include "r_data/sprites.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
|
|
||||||
void ClearSaveGames();
|
void ClearSaveGames();
|
||||||
|
@ -135,6 +136,7 @@ DEFINE_ACTION_FUNCTION(FOptionValues, GetText)
|
||||||
|
|
||||||
void DeinitMenus()
|
void DeinitMenus()
|
||||||
{
|
{
|
||||||
|
M_ClearMenus();
|
||||||
{
|
{
|
||||||
FOptionMap::Iterator it(OptionValues);
|
FOptionMap::Iterator it(OptionValues);
|
||||||
|
|
||||||
|
@ -148,7 +150,6 @@ void DeinitMenus()
|
||||||
}
|
}
|
||||||
MenuDescriptors.Clear();
|
MenuDescriptors.Clear();
|
||||||
OptionValues.Clear();
|
OptionValues.Clear();
|
||||||
CurrentMenu = nullptr;
|
|
||||||
savegameManager.ClearSaveGames();
|
savegameManager.ClearSaveGames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4819,7 +4819,10 @@ void AActor::OnDestroy ()
|
||||||
// note that this differs from ThingSpawned in that you can actually override OnDestroy to avoid calling the hook.
|
// note that this differs from ThingSpawned in that you can actually override OnDestroy to avoid calling the hook.
|
||||||
// but you can't really do that without utterly breaking the game, so it's ok.
|
// but you can't really do that without utterly breaking the game, so it's ok.
|
||||||
// note: if OnDestroy is ever made optional, E_WorldThingDestroyed should still be called for ANY thing.
|
// note: if OnDestroy is ever made optional, E_WorldThingDestroyed should still be called for ANY thing.
|
||||||
Level->localEventManager->WorldThingDestroyed(this);
|
if (Level != nullptr)
|
||||||
|
{
|
||||||
|
Level->localEventManager->WorldThingDestroyed(this);
|
||||||
|
}
|
||||||
|
|
||||||
DeleteAttachedLights();
|
DeleteAttachedLights();
|
||||||
ClearRenderSectorList();
|
ClearRenderSectorList();
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "fragglescript/t_script.h"
|
#include "fragglescript/t_script.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position);
|
extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "m_joy.h"
|
#include "m_joy.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, joy_axespolling)
|
EXTERN_CVAR(Bool, joy_axespolling)
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "i_common.h"
|
#include "i_common.h"
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
@ -61,60 +62,6 @@ EXTERN_CVAR(Bool, vid_vsync )
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
// The maximum number of functions that can be registered with atterm.
|
|
||||||
const size_t MAX_TERMS = 64;
|
|
||||||
|
|
||||||
void (*TermFuncs[MAX_TERMS])();
|
|
||||||
const char *TermNames[MAX_TERMS];
|
|
||||||
size_t NumTerms;
|
|
||||||
|
|
||||||
} // unnamed namespace
|
|
||||||
|
|
||||||
// Expose this for i_main_except.cpp
|
|
||||||
void call_terms()
|
|
||||||
{
|
|
||||||
while (NumTerms > 0)
|
|
||||||
{
|
|
||||||
TermFuncs[--NumTerms]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void addterm(void (*func)(), const char *name)
|
|
||||||
{
|
|
||||||
// Make sure this function wasn't already registered.
|
|
||||||
|
|
||||||
for (size_t i = 0; i < NumTerms; ++i)
|
|
||||||
{
|
|
||||||
if (TermFuncs[i] == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NumTerms == MAX_TERMS)
|
|
||||||
{
|
|
||||||
func();
|
|
||||||
I_FatalError("Too many exit functions registered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
TermNames[NumTerms] = name;
|
|
||||||
TermFuncs[NumTerms] = func;
|
|
||||||
|
|
||||||
++NumTerms;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popterm()
|
|
||||||
{
|
|
||||||
if (NumTerms)
|
|
||||||
{
|
|
||||||
--NumTerms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Mac_I_FatalError(const char* const message)
|
void Mac_I_FatalError(const char* const message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,9 +36,9 @@
|
||||||
|
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// Import some functions from i_main.mm
|
// Import some functions from i_main.mm
|
||||||
void call_terms();
|
|
||||||
void Mac_I_FatalError(const char* const message);
|
void Mac_I_FatalError(const char* const message);
|
||||||
void OriginalMainTry(int argc, char** argv);
|
void OriginalMainTry(int argc, char** argv);
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
|
|
||||||
EXTERN_CVAR(String, language)
|
EXTERN_CVAR(String, language)
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
#include "vulkan/system/vk_framebuffer.h"
|
#include "vulkan/system/vk_framebuffer.h"
|
||||||
|
|
|
@ -89,10 +89,6 @@ void I_Quit (void);
|
||||||
|
|
||||||
void I_Tactile (int on, int off, int total);
|
void I_Tactile (int on, int off, int total);
|
||||||
|
|
||||||
void addterm (void (*func)(void), const char *name);
|
|
||||||
#define atterm(t) addterm (t, #t)
|
|
||||||
void popterm ();
|
|
||||||
|
|
||||||
void I_DebugPrint (const char *cp);
|
void I_DebugPrint (const char *cp);
|
||||||
|
|
||||||
// Print a console string
|
// Print a console string
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "swrenderer/r_swrenderer.h"
|
#include "swrenderer/r_swrenderer.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
IVideo *Video;
|
IVideo *Video;
|
||||||
|
|
||||||
|
|
|
@ -306,54 +306,63 @@ void MessagePump (const SDL_Event &sev)
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
case SDL_MOUSEBUTTONUP:
|
case SDL_MOUSEBUTTONUP:
|
||||||
case SDL_MOUSEMOTION:
|
if (!GUICapture)
|
||||||
if (!GUICapture || sev.button.button == 4 || sev.button.button == 5)
|
|
||||||
{
|
{
|
||||||
if(sev.type != SDL_MOUSEMOTION)
|
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
|
||||||
|
|
||||||
|
switch (sev.button.button)
|
||||||
{
|
{
|
||||||
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
|
case SDL_BUTTON_LEFT: event.data1 = KEY_MOUSE1; break;
|
||||||
/* These button mappings work with my Gentoo system using the
|
case SDL_BUTTON_MIDDLE: event.data1 = KEY_MOUSE3; break;
|
||||||
* evdev driver and a Logitech MX510 mouse. Whether or not they
|
case SDL_BUTTON_RIGHT: event.data1 = KEY_MOUSE2; break;
|
||||||
* carry over to other Linux systems, I have no idea, but I sure
|
case SDL_BUTTON_X1: event.data1 = KEY_MOUSE4; break;
|
||||||
* hope so. (Though buttons 11 and 12 are kind of useless, since
|
case SDL_BUTTON_X2: event.data1 = KEY_MOUSE5; break;
|
||||||
* they also trigger buttons 4 and 5.)
|
case 6: event.data1 = KEY_MOUSE6; break;
|
||||||
*/
|
case 7: event.data1 = KEY_MOUSE7; break;
|
||||||
switch (sev.button.button)
|
case 8: event.data1 = KEY_MOUSE8; break;
|
||||||
{
|
default: printf("SDL mouse button %s %d\n",
|
||||||
case SDL_BUTTON_LEFT: event.data1 = KEY_MOUSE1; break;
|
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
|
||||||
case SDL_BUTTON_MIDDLE: event.data1 = KEY_MOUSE3; break;
|
}
|
||||||
case SDL_BUTTON_RIGHT: event.data1 = KEY_MOUSE2; break;
|
|
||||||
case 8: event.data1 = KEY_MOUSE4; break; // For whatever reason my side mouse buttons are here.
|
if (event.data1 != 0)
|
||||||
case 9: event.data1 = KEY_MOUSE5; break;
|
{
|
||||||
case SDL_BUTTON_X1: event.data1 = KEY_MOUSE6; break; // And these don't exist
|
D_PostEvent(&event);
|
||||||
case SDL_BUTTON_X2: event.data1 = KEY_MOUSE7; break;
|
|
||||||
case 6: event.data1 = KEY_MOUSE8; break;
|
|
||||||
default: printf("SDL mouse button %s %d\n",
|
|
||||||
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
|
|
||||||
}
|
|
||||||
if (event.data1 != 0)
|
|
||||||
{
|
|
||||||
D_PostEvent(&event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sev.type == SDL_MOUSEMOTION || (sev.button.button >= 1 && sev.button.button <= 3))
|
else if ((sev.button.button >= SDL_BUTTON_LEFT && sev.button.button <= SDL_BUTTON_X2))
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
SDL_GetMouseState (&x, &y);
|
SDL_GetMouseState(&x, &y);
|
||||||
|
|
||||||
|
event.type = EV_GUI_Event;
|
||||||
event.data1 = x;
|
event.data1 = x;
|
||||||
event.data2 = y;
|
event.data2 = y;
|
||||||
|
|
||||||
screen->ScaleCoordsFromWindow(event.data1, event.data2);
|
screen->ScaleCoordsFromWindow(event.data1, event.data2);
|
||||||
|
|
||||||
event.type = EV_GUI_Event;
|
if (sev.type == SDL_MOUSEBUTTONDOWN)
|
||||||
if(sev.type == SDL_MOUSEMOTION)
|
{
|
||||||
event.subtype = EV_GUI_MouseMove;
|
switch(sev.button.button)
|
||||||
|
{
|
||||||
|
case SDL_BUTTON_LEFT: event.subtype = EV_GUI_LButtonDown; break;
|
||||||
|
case SDL_BUTTON_MIDDLE: event.subtype = EV_GUI_MButtonDown; break;
|
||||||
|
case SDL_BUTTON_RIGHT: event.subtype = EV_GUI_RButtonDown; break;
|
||||||
|
case SDL_BUTTON_X1: event.subtype = EV_GUI_BackButtonDown; break;
|
||||||
|
case SDL_BUTTON_X2: event.subtype = EV_GUI_FwdButtonDown; break;
|
||||||
|
default: assert(false); event.subtype = EV_GUI_None; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
event.subtype = sev.type == SDL_MOUSEBUTTONDOWN ? EV_GUI_LButtonDown : EV_GUI_LButtonUp;
|
switch(sev.button.button)
|
||||||
event.subtype += (sev.button.button - 1) * 3;
|
{
|
||||||
|
case SDL_BUTTON_LEFT: event.subtype = EV_GUI_LButtonUp; break;
|
||||||
|
case SDL_BUTTON_MIDDLE: event.subtype = EV_GUI_MButtonUp; break;
|
||||||
|
case SDL_BUTTON_RIGHT: event.subtype = EV_GUI_RButtonUp; break;
|
||||||
|
case SDL_BUTTON_X1: event.subtype = EV_GUI_BackButtonUp; break;
|
||||||
|
case SDL_BUTTON_X2: event.subtype = EV_GUI_FwdButtonUp; break;
|
||||||
|
default: assert(false); event.subtype = EV_GUI_None; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Keymod kmod = SDL_GetModState();
|
SDL_Keymod kmod = SDL_GetModState();
|
||||||
|
@ -365,15 +374,41 @@ void MessagePump (const SDL_Event &sev)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
if (GUICapture)
|
||||||
|
{
|
||||||
|
event.data1 = sev.motion.x;
|
||||||
|
event.data2 = sev.motion.y;
|
||||||
|
|
||||||
|
screen->ScaleCoordsFromWindow(event.data1, event.data2);
|
||||||
|
|
||||||
|
event.type = EV_GUI_Event;
|
||||||
|
event.subtype = EV_GUI_MouseMove;
|
||||||
|
|
||||||
|
SDL_Keymod kmod = SDL_GetModState();
|
||||||
|
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
|
||||||
|
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
|
||||||
|
((kmod & KMOD_ALT) ? GKM_ALT : 0);
|
||||||
|
|
||||||
|
D_PostEvent(&event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEWHEEL:
|
case SDL_MOUSEWHEEL:
|
||||||
if (GUICapture)
|
if (GUICapture)
|
||||||
{
|
{
|
||||||
event.type = EV_GUI_Event;
|
event.type = EV_GUI_Event;
|
||||||
event.subtype = sev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown;
|
|
||||||
|
if (sev.wheel.y == 0)
|
||||||
|
event.subtype = sev.wheel.x > 0 ? EV_GUI_WheelRight : EV_GUI_WheelLeft;
|
||||||
|
else
|
||||||
|
event.subtype = sev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown;
|
||||||
|
|
||||||
SDL_Keymod kmod = SDL_GetModState();
|
SDL_Keymod kmod = SDL_GetModState();
|
||||||
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
|
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
|
||||||
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
|
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
|
||||||
((kmod & KMOD_ALT) ? GKM_ALT : 0);
|
((kmod & KMOD_ALT) ? GKM_ALT : 0);
|
||||||
|
|
||||||
D_PostEvent (&event);
|
D_PostEvent (&event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -89,47 +90,9 @@ FArgs *Args;
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static void (*TermFuncs[MAX_TERMS]) ();
|
|
||||||
static const char *TermNames[MAX_TERMS];
|
|
||||||
static int NumTerms;
|
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
void addterm (void (*func) (), const char *name)
|
|
||||||
{
|
|
||||||
// Make sure this function wasn't already registered.
|
|
||||||
for (int i = 0; i < NumTerms; ++i)
|
|
||||||
{
|
|
||||||
if (TermFuncs[i] == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (NumTerms == MAX_TERMS)
|
|
||||||
{
|
|
||||||
func ();
|
|
||||||
I_FatalError (
|
|
||||||
"Too many exit functions registered.\n"
|
|
||||||
"Increase MAX_TERMS in i_main.cpp");
|
|
||||||
}
|
|
||||||
TermNames[NumTerms] = name;
|
|
||||||
TermFuncs[NumTerms++] = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popterm ()
|
|
||||||
{
|
|
||||||
if (NumTerms)
|
|
||||||
NumTerms--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void call_terms ()
|
|
||||||
{
|
|
||||||
while (NumTerms > 0)
|
|
||||||
{
|
|
||||||
// printf ("term %d - %s\n", NumTerms, TermNames[NumTerms-1]);
|
|
||||||
TermFuncs[--NumTerms] ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void NewFailure ()
|
static void NewFailure ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
#include "gameconfigfile.h"
|
#include "gameconfigfile.h"
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -388,7 +388,7 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
|
||||||
side + j * 3 + // Current surface and previous triangles
|
side + j * 3 + // Current surface and previous triangles
|
||||||
surfaces[i].vbStart; // Previous surfaces
|
surfaces[i].vbStart; // Previous surfaces
|
||||||
|
|
||||||
OBJFaceSide &curSide = surfaces[i].tris[j].sides[side];
|
OBJFaceSide &curSide = surfaces[i].tris[j].sides[2 - side];
|
||||||
|
|
||||||
int vidx = curSide.vertref;
|
int vidx = curSide.vertref;
|
||||||
int uvidx = (curSide.uvref >= 0 && (unsigned int)curSide.uvref < uvs.Size()) ? curSide.uvref : 0;
|
int uvidx = (curSide.uvref >= 0 && (unsigned int)curSide.uvref < uvs.Size()) ? curSide.uvref : 0;
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "actorinlines.h"
|
#include "actorinlines.h"
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -35,13 +35,61 @@
|
||||||
|
|
||||||
EXTERN_CVAR(Float, transsouls)
|
EXTERN_CVAR(Float, transsouls)
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(DShape2DTransform, false, false)
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2DTransform, Clear)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2DTransform);
|
||||||
|
self->transform.Identity();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2DTransform, Rotate)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2DTransform);
|
||||||
|
PARAM_FLOAT(angle);
|
||||||
|
self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2DTransform, Scale)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2DTransform);
|
||||||
|
PARAM_FLOAT(x);
|
||||||
|
PARAM_FLOAT(y);
|
||||||
|
self->transform = DMatrix3x3::Scale2D(DVector2(x, y)) * self->transform;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2DTransform, Translate)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2DTransform);
|
||||||
|
PARAM_FLOAT(x);
|
||||||
|
PARAM_FLOAT(y);
|
||||||
|
self->transform = DMatrix3x3::Translate2D(DVector2(x, y)) * self->transform;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
IMPLEMENT_CLASS(DShape2D, false, false)
|
IMPLEMENT_CLASS(DShape2D, false, false)
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2D, SetTransform)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2D);
|
||||||
|
PARAM_OBJECT(transform, DShape2DTransform);
|
||||||
|
self->transform = transform->transform;
|
||||||
|
self->dirty = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DShape2D, Clear)
|
DEFINE_ACTION_FUNCTION(DShape2D, Clear)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(DShape2D);
|
PARAM_SELF_PROLOGUE(DShape2D);
|
||||||
PARAM_INT(which);
|
PARAM_INT(which);
|
||||||
if ( which&C_Verts ) self->mVertices.Clear();
|
if ( which&C_Verts )
|
||||||
|
{
|
||||||
|
self->mVertices.Clear();
|
||||||
|
self->dirty = true;
|
||||||
|
}
|
||||||
if ( which&C_Coords ) self->mCoords.Clear();
|
if ( which&C_Coords ) self->mCoords.Clear();
|
||||||
if ( which&C_Indices ) self->mIndices.Clear();
|
if ( which&C_Indices ) self->mIndices.Clear();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -53,6 +101,7 @@ DEFINE_ACTION_FUNCTION(DShape2D, PushVertex)
|
||||||
PARAM_FLOAT(x);
|
PARAM_FLOAT(x);
|
||||||
PARAM_FLOAT(y);
|
PARAM_FLOAT(y);
|
||||||
self->mVertices.Push(DVector2(x,y));
|
self->mVertices.Push(DVector2(x,y));
|
||||||
|
self->dirty = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,13 +429,22 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
|
||||||
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
|
if (!img->isHardwareCanvas() && parms.remap != nullptr && !parms.remap->Inactive)
|
||||||
dg.mTranslation = parms.remap;
|
dg.mTranslation = parms.remap;
|
||||||
|
|
||||||
|
if (shape->dirty) {
|
||||||
|
if (shape->mVertices.Size() != shape->mTransformedVertices.Size())
|
||||||
|
shape->mTransformedVertices.Resize(shape->mVertices.Size());
|
||||||
|
for (int i = 0; i < dg.mVertCount; i++) {
|
||||||
|
shape->mTransformedVertices[i] = (shape->transform * DVector3(shape->mVertices[i], 1.0)).XY();
|
||||||
|
}
|
||||||
|
shape->dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384;
|
double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384;
|
||||||
for ( int i=0; i<dg.mVertCount; i++ )
|
for ( int i=0; i<dg.mVertCount; i++ )
|
||||||
{
|
{
|
||||||
if ( shape->mVertices[i].X < minx ) minx = shape->mVertices[i].X;
|
if ( shape->mTransformedVertices[i].X < minx ) minx = shape->mTransformedVertices[i].X;
|
||||||
if ( shape->mVertices[i].Y < miny ) miny = shape->mVertices[i].Y;
|
if ( shape->mTransformedVertices[i].Y < miny ) miny = shape->mTransformedVertices[i].Y;
|
||||||
if ( shape->mVertices[i].X > maxx ) maxx = shape->mVertices[i].X;
|
if ( shape->mTransformedVertices[i].X > maxx ) maxx = shape->mTransformedVertices[i].X;
|
||||||
if ( shape->mVertices[i].Y > maxy ) maxy = shape->mVertices[i].Y;
|
if ( shape->mTransformedVertices[i].Y > maxy ) maxy = shape->mTransformedVertices[i].Y;
|
||||||
}
|
}
|
||||||
if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip)
|
if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip)
|
||||||
{
|
{
|
||||||
|
@ -402,7 +460,7 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
|
||||||
dg.mVertIndex = (int)mVertices.Reserve(dg.mVertCount);
|
dg.mVertIndex = (int)mVertices.Reserve(dg.mVertCount);
|
||||||
TwoDVertex *ptr = &mVertices[dg.mVertIndex];
|
TwoDVertex *ptr = &mVertices[dg.mVertIndex];
|
||||||
for ( int i=0; i<dg.mVertCount; i++ )
|
for ( int i=0; i<dg.mVertCount; i++ )
|
||||||
ptr[i].Set(shape->mVertices[i].X, shape->mVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor);
|
ptr[i].Set(shape->mTransformedVertices[i].X, shape->mTransformedVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor);
|
||||||
dg.mIndexIndex = mIndices.Size();
|
dg.mIndexIndex = mIndices.Size();
|
||||||
dg.mIndexCount += shape->mIndices.Size();
|
dg.mIndexCount += shape->mIndices.Size();
|
||||||
for ( int i=0; i<int(shape->mIndices.Size()); i+=3 )
|
for ( int i=0; i<int(shape->mIndices.Size()); i+=3 )
|
||||||
|
@ -485,10 +543,10 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
||||||
mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
|
mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
|
||||||
}
|
}
|
||||||
poly.mIndexIndex = mIndices.Size();
|
poly.mIndexIndex = mIndices.Size();
|
||||||
poly.mIndexCount += (npoints - 2) * 3;
|
|
||||||
|
|
||||||
if (indices == nullptr || indexcount == 0)
|
if (indices == nullptr || indexcount == 0)
|
||||||
{
|
{
|
||||||
|
poly.mIndexCount += (npoints - 2) * 3;
|
||||||
for (int i = 2; i < npoints; ++i)
|
for (int i = 2; i < npoints; ++i)
|
||||||
{
|
{
|
||||||
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
|
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
|
||||||
|
@ -496,10 +554,11 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
poly.mIndexCount += (int)indexcount;
|
||||||
int addr = mIndices.Reserve(indexcount);
|
int addr = mIndices.Reserve(indexcount);
|
||||||
for (size_t i = 0; i < indexcount; i++)
|
for (size_t i = 0; i < indexcount; i++)
|
||||||
{
|
{
|
||||||
mIndices[addr + i] = addr + indices[i];
|
mIndices[addr + i] = poly.mVertIndex + indices[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,18 @@
|
||||||
|
|
||||||
struct DrawParms;
|
struct DrawParms;
|
||||||
|
|
||||||
|
class DShape2DTransform : public DObject
|
||||||
|
{
|
||||||
|
|
||||||
|
DECLARE_CLASS(DShape2DTransform, DObject)
|
||||||
|
public:
|
||||||
|
DShape2DTransform()
|
||||||
|
{
|
||||||
|
transform.Identity();
|
||||||
|
}
|
||||||
|
DMatrix3x3 transform;
|
||||||
|
};
|
||||||
|
|
||||||
// intermediate struct for shape drawing
|
// intermediate struct for shape drawing
|
||||||
|
|
||||||
enum EClearWhich
|
enum EClearWhich
|
||||||
|
@ -23,9 +35,21 @@ class DShape2D : public DObject
|
||||||
|
|
||||||
DECLARE_CLASS(DShape2D,DObject)
|
DECLARE_CLASS(DShape2D,DObject)
|
||||||
public:
|
public:
|
||||||
|
DShape2D()
|
||||||
|
{
|
||||||
|
transform.Identity();
|
||||||
|
}
|
||||||
|
|
||||||
TArray<int> mIndices;
|
TArray<int> mIndices;
|
||||||
TArray<DVector2> mVertices;
|
TArray<DVector2> mVertices;
|
||||||
TArray<DVector2> mCoords;
|
TArray<DVector2> mCoords;
|
||||||
|
|
||||||
|
DMatrix3x3 transform;
|
||||||
|
|
||||||
|
// dirty stores whether we need to re-apply the transformation
|
||||||
|
// otherwise it uses the cached values
|
||||||
|
bool dirty = true;
|
||||||
|
TArray<DVector2> mTransformedVertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
class F2DDrawer
|
class F2DDrawer
|
||||||
|
|
|
@ -235,7 +235,8 @@ void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma)
|
||||||
}
|
}
|
||||||
mPresentShader->Uniforms->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() };
|
mPresentShader->Uniforms->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() };
|
||||||
mPresentShader->Uniforms->Offset = { 0.0f, 0.0f };
|
mPresentShader->Uniforms->Offset = { 0.0f, 0.0f };
|
||||||
mPresentShader->Uniforms.Set();
|
mPresentShader->Uniforms.SetData();
|
||||||
|
static_cast<GLDataBuffer*>(mPresentShader->Uniforms.GetBuffer())->BindBase();
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "gl/renderer/gl_renderbuffers.h"
|
#include "gl/renderer/gl_renderbuffers.h"
|
||||||
#include "gl/renderer/gl_postprocessstate.h"
|
#include "gl/renderer/gl_postprocessstate.h"
|
||||||
#include "gl/shaders/gl_shaderprogram.h"
|
#include "gl/shaders/gl_shaderprogram.h"
|
||||||
|
#include "gl/system/gl_buffers.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||||
|
@ -955,7 +956,7 @@ void GLPPRenderState::Draw()
|
||||||
if (!shader->Uniforms)
|
if (!shader->Uniforms)
|
||||||
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false, false));
|
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false, false));
|
||||||
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data());
|
shader->Uniforms->SetData(Uniforms.Data.Size(), Uniforms.Data.Data());
|
||||||
shader->Uniforms->BindBase();
|
static_cast<GLDataBuffer*>(shader->Uniforms.get())->BindBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set shader
|
// Set shader
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#include "r_videoscale.h"
|
#include "r_videoscale.h"
|
||||||
#include "r_data/models/models.h"
|
#include "r_data/models/models.h"
|
||||||
#include "gl/renderer/gl_postprocessstate.h"
|
#include "gl/renderer/gl_postprocessstate.h"
|
||||||
|
#include "gl/system/gl_buffers.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Int, screenblocks)
|
EXTERN_CVAR(Int, screenblocks)
|
||||||
EXTERN_CVAR(Bool, cl_capfps)
|
EXTERN_CVAR(Bool, cl_capfps)
|
||||||
|
@ -191,12 +192,17 @@ void FGLRenderer::UpdateShadowMap()
|
||||||
|
|
||||||
FGLPostProcessState savedState;
|
FGLPostProcessState savedState;
|
||||||
|
|
||||||
|
static_cast<GLDataBuffer*>(screen->mShadowMap.mLightList)->BindBase();
|
||||||
|
static_cast<GLDataBuffer*>(screen->mShadowMap.mNodesBuffer)->BindBase();
|
||||||
|
static_cast<GLDataBuffer*>(screen->mShadowMap.mLinesBuffer)->BindBase();
|
||||||
|
|
||||||
mBuffers->BindShadowMapFB();
|
mBuffers->BindShadowMapFB();
|
||||||
|
|
||||||
mShadowMapShader->Bind();
|
mShadowMapShader->Bind();
|
||||||
mShadowMapShader->Uniforms->ShadowmapQuality = gl_shadowmap_quality;
|
mShadowMapShader->Uniforms->ShadowmapQuality = gl_shadowmap_quality;
|
||||||
mShadowMapShader->Uniforms->NodesCount = screen->mShadowMap.NodesCount();
|
mShadowMapShader->Uniforms->NodesCount = screen->mShadowMap.NodesCount();
|
||||||
mShadowMapShader->Uniforms.Set();
|
mShadowMapShader->Uniforms.SetData();
|
||||||
|
static_cast<GLDataBuffer*>(mShadowMapShader->Uniforms.GetBuffer())->BindBase();
|
||||||
|
|
||||||
glViewport(0, 0, gl_shadowmap_quality, 1024);
|
glViewport(0, 0, gl_shadowmap_quality, 1024);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
|
@ -27,7 +27,7 @@ class FGLRenderBuffers;
|
||||||
class FGL2DDrawer;
|
class FGL2DDrawer;
|
||||||
class FHardwareTexture;
|
class FHardwareTexture;
|
||||||
class SWSceneDrawer;
|
class SWSceneDrawer;
|
||||||
class GLViewpointBuffer;
|
class HWViewpointBuffer;
|
||||||
struct FRenderViewpoint;
|
struct FRenderViewpoint;
|
||||||
|
|
||||||
namespace OpenGLRenderer
|
namespace OpenGLRenderer
|
||||||
|
|
|
@ -189,9 +189,21 @@ bool FGLRenderState::ApplyShader()
|
||||||
matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index);
|
matrixToGL(identityMatrix, activeShader->normalmodelmatrix_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto index = screen->mLights->BindUBO(mLightIndex);
|
int index = mLightIndex;
|
||||||
activeShader->muLightIndex.Set(index);
|
// Mess alert for crappy AncientGL!
|
||||||
|
if (!screen->mLights->GetBufferType() && index >= 0)
|
||||||
|
{
|
||||||
|
size_t start, size;
|
||||||
|
index = screen->mLights->GetBinding(index, &start, &size);
|
||||||
|
|
||||||
|
if (start != mLastMappedLightIndex)
|
||||||
|
{
|
||||||
|
mLastMappedLightIndex = start;
|
||||||
|
static_cast<GLDataBuffer*>(screen->mLights->GetBuffer())->BindRange(nullptr, start, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activeShader->muLightIndex.Set(index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ class FGLRenderState : public FRenderState
|
||||||
int lastClamp = 0;
|
int lastClamp = 0;
|
||||||
int lastTranslation = 0;
|
int lastTranslation = 0;
|
||||||
int maxBoundMaterial = -1;
|
int maxBoundMaterial = -1;
|
||||||
|
size_t mLastMappedLightIndex = SIZE_MAX;
|
||||||
|
|
||||||
IVertexBuffer *mCurrentVertexBuffer;
|
IVertexBuffer *mCurrentVertexBuffer;
|
||||||
int mCurrentVertexOffsets[2]; // one per binding point
|
int mCurrentVertexOffsets[2]; // one per binding point
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "hwrenderer/scene/hw_portal.h"
|
#include "hwrenderer/scene/hw_portal.h"
|
||||||
#include "hwrenderer/utility/hw_vrmodes.h"
|
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||||
#include "gl/renderer/gl_renderer.h"
|
#include "gl/renderer/gl_renderer.h"
|
||||||
|
#include "gl/system/gl_buffers.h"
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "gl/renderer/gl_postprocessstate.h"
|
#include "gl/renderer/gl_postprocessstate.h"
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
#include "gl/shaders/gl_shaderprogram.h"
|
#include "gl/shaders/gl_shaderprogram.h"
|
||||||
|
#include "gl/system/gl_buffers.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Int, vr_mode)
|
EXTERN_CVAR(Int, vr_mode)
|
||||||
|
@ -174,7 +175,8 @@ void FGLRenderer::prepareInterleavedPresent(FPresentShaderBase& shader)
|
||||||
screen->mScreenViewport.height / (float)mBuffers->GetHeight()
|
screen->mScreenViewport.height / (float)mBuffers->GetHeight()
|
||||||
};
|
};
|
||||||
shader.Uniforms->Offset = { 0.0f, 0.0f };
|
shader.Uniforms->Offset = { 0.0f, 0.0f };
|
||||||
shader.Uniforms.Set();
|
shader.Uniforms.SetData();
|
||||||
|
static_cast<GLDataBuffer*>(shader.Uniforms.GetBuffer())->BindBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -198,7 +200,8 @@ void FGLRenderer::PresentColumnInterleaved()
|
||||||
int windowHOffset = 0;
|
int windowHOffset = 0;
|
||||||
|
|
||||||
mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
|
mPresent3dColumnShader->Uniforms->WindowPositionParity = windowHOffset;
|
||||||
mPresent3dColumnShader->Uniforms.Set();
|
mPresent3dColumnShader->Uniforms.SetData();
|
||||||
|
static_cast<GLDataBuffer*>(mPresent3dColumnShader->Uniforms.GetBuffer())->BindBase();
|
||||||
|
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
}
|
}
|
||||||
|
@ -225,7 +228,8 @@ void FGLRenderer::PresentRowInterleaved()
|
||||||
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
||||||
) % 2;
|
) % 2;
|
||||||
|
|
||||||
mPresent3dRowShader->Uniforms.Set();
|
mPresent3dRowShader->Uniforms.SetData();
|
||||||
|
static_cast<GLDataBuffer*>(mPresent3dRowShader->Uniforms.GetBuffer())->BindBase();
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +260,8 @@ void FGLRenderer::PresentCheckerInterleaved()
|
||||||
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
+ screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom
|
||||||
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
|
) % 2; // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset
|
||||||
|
|
||||||
mPresent3dCheckerShader->Uniforms.Set();
|
mPresent3dCheckerShader->Uniforms.SetData();
|
||||||
|
static_cast<GLDataBuffer*>(mPresent3dCheckerShader->Uniforms.GetBuffer())->BindBase();
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,10 +210,9 @@ void GLVertexBuffer::Bind(int *offsets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDataBuffer::BindRange(size_t start, size_t length)
|
void GLDataBuffer::BindRange(FRenderState *state, size_t start, size_t length)
|
||||||
{
|
{
|
||||||
if (mUseType == GL_UNIFORM_BUFFER) // SSBO's cannot be rebound.
|
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
|
||||||
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDataBuffer::BindBase()
|
void GLDataBuffer::BindBase()
|
||||||
|
|
|
@ -66,8 +66,8 @@ class GLDataBuffer : public IDataBuffer, public GLBuffer
|
||||||
int mBindingPoint;
|
int mBindingPoint;
|
||||||
public:
|
public:
|
||||||
GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(is_ssbo? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER), mBindingPoint(bindingpoint) {}
|
GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(is_ssbo? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER), mBindingPoint(bindingpoint) {}
|
||||||
void BindRange(size_t start, size_t length) override;
|
void BindRange(FRenderState* state, size_t start, size_t length);
|
||||||
void BindBase() override;
|
void BindBase();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -126,7 +126,7 @@ void OpenGLFrameBuffer::InitializeState()
|
||||||
glslversion = gl.glslversion;
|
glslversion = gl.glslversion;
|
||||||
uniformblockalignment = gl.uniformblockalignment;
|
uniformblockalignment = gl.uniformblockalignment;
|
||||||
maxuniformblock = gl.maxuniformblock;
|
maxuniformblock = gl.maxuniformblock;
|
||||||
gl_vendorstring = gl.vendorstring;
|
vendorstring = gl.vendorstring;
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
@ -154,12 +154,14 @@ void OpenGLFrameBuffer::InitializeState()
|
||||||
|
|
||||||
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
||||||
mSkyData = new FSkyVertexBuffer;
|
mSkyData = new FSkyVertexBuffer;
|
||||||
mViewpoints = new GLViewpointBuffer;
|
mViewpoints = new HWViewpointBuffer;
|
||||||
mLights = new FLightBuffer();
|
mLights = new FLightBuffer();
|
||||||
|
|
||||||
GLRenderer = new FGLRenderer(this);
|
GLRenderer = new FGLRenderer(this);
|
||||||
GLRenderer->Initialize(GetWidth(), GetHeight());
|
GLRenderer->Initialize(GetWidth(), GetHeight());
|
||||||
|
|
||||||
|
static_cast<GLDataBuffer*>(mLights->GetBuffer())->BindBase();
|
||||||
|
|
||||||
mDebug = std::make_shared<FGLDebug>();
|
mDebug = std::make_shared<FGLDebug>();
|
||||||
mDebug->Update();
|
mDebug->Update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ void gl_LoadExtensions()
|
||||||
|
|
||||||
// Mesa implements shader storage only for fragment shaders.
|
// Mesa implements shader storage only for fragment shaders.
|
||||||
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
|
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
|
||||||
int v;
|
int v = 0;
|
||||||
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
|
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
|
||||||
if (v == 0)
|
if (v == 0)
|
||||||
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;
|
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
class FRenderState;
|
||||||
|
|
||||||
// The low level code needs to know which attributes exist.
|
// The low level code needs to know which attributes exist.
|
||||||
// OpenGL needs to change the state of all of them per buffer binding.
|
// OpenGL needs to change the state of all of them per buffer binding.
|
||||||
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
|
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
|
||||||
|
@ -76,7 +78,6 @@ class IDataBuffer : virtual public IBuffer
|
||||||
{
|
{
|
||||||
// Can be either uniform or shader storage buffer, depending on its needs.
|
// Can be either uniform or shader storage buffer, depending on its needs.
|
||||||
public:
|
public:
|
||||||
virtual void BindRange(size_t start, size_t length) = 0;
|
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
|
||||||
virtual void BindBase() = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
|
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
|
||||||
|
|
||||||
GLViewpointBuffer::GLViewpointBuffer()
|
HWViewpointBuffer::HWViewpointBuffer()
|
||||||
{
|
{
|
||||||
mBufferSize = INITIAL_BUFFER_SIZE;
|
mBufferSize = INITIAL_BUFFER_SIZE;
|
||||||
mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment;
|
mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment;
|
||||||
|
@ -45,13 +45,13 @@ GLViewpointBuffer::GLViewpointBuffer()
|
||||||
mClipPlaneInfo.Push(0);
|
mClipPlaneInfo.Push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLViewpointBuffer::~GLViewpointBuffer()
|
HWViewpointBuffer::~HWViewpointBuffer()
|
||||||
{
|
{
|
||||||
delete mBuffer;
|
delete mBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLViewpointBuffer::CheckSize()
|
void HWViewpointBuffer::CheckSize()
|
||||||
{
|
{
|
||||||
if (mUploadIndex >= mBufferSize)
|
if (mUploadIndex >= mBufferSize)
|
||||||
{
|
{
|
||||||
|
@ -62,18 +62,18 @@ void GLViewpointBuffer::CheckSize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLViewpointBuffer::Bind(FRenderState &di, unsigned int index)
|
int HWViewpointBuffer::Bind(FRenderState &di, unsigned int index)
|
||||||
{
|
{
|
||||||
if (index != mLastMappedIndex)
|
if (index != mLastMappedIndex)
|
||||||
{
|
{
|
||||||
mLastMappedIndex = index;
|
mLastMappedIndex = index;
|
||||||
mBuffer->BindRange(index * mBlockAlign, mBlockAlign);
|
mBuffer->BindRange(&di, index * mBlockAlign, mBlockAlign);
|
||||||
di.EnableClipDistance(0, mClipPlaneInfo[index]);
|
di.EnableClipDistance(0, mClipPlaneInfo[index]);
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
|
void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height)
|
||||||
{
|
{
|
||||||
if (width != m2DWidth || height != m2DHeight)
|
if (width != m2DWidth || height != m2DHeight)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@ void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height)
|
||||||
Bind(di, 0);
|
Bind(di, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
|
int HWViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
|
||||||
{
|
{
|
||||||
CheckSize();
|
CheckSize();
|
||||||
mBuffer->Map();
|
mBuffer->Map();
|
||||||
|
@ -102,7 +102,7 @@ int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp)
|
||||||
return Bind(di, mUploadIndex++);
|
return Bind(di, mUploadIndex++);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLViewpointBuffer::Clear()
|
void HWViewpointBuffer::Clear()
|
||||||
{
|
{
|
||||||
// Index 0 is reserved for the 2D projection.
|
// Index 0 is reserved for the 2D projection.
|
||||||
mUploadIndex = 1;
|
mUploadIndex = 1;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
struct HWViewpointUniforms;
|
struct HWViewpointUniforms;
|
||||||
class FRenderState;
|
class FRenderState;
|
||||||
|
|
||||||
class GLViewpointBuffer
|
class HWViewpointBuffer
|
||||||
{
|
{
|
||||||
IDataBuffer *mBuffer;
|
IDataBuffer *mBuffer;
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ class GLViewpointBuffer
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
GLViewpointBuffer();
|
HWViewpointBuffer();
|
||||||
~GLViewpointBuffer();
|
~HWViewpointBuffer();
|
||||||
void Clear();
|
void Clear();
|
||||||
int Bind(FRenderState &di, unsigned int index);
|
int Bind(FRenderState &di, unsigned int index);
|
||||||
void Set2D(FRenderState &di, int width, int height);
|
void Set2D(FRenderState &di, int width, int height);
|
||||||
|
|
|
@ -126,14 +126,16 @@ public:
|
||||||
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
|
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Set(bool bind = true)
|
void SetData()
|
||||||
{
|
{
|
||||||
if (mBuffer != nullptr)
|
if (mBuffer != nullptr)
|
||||||
mBuffer->SetData(sizeof(T), &Values);
|
mBuffer->SetData(sizeof(T), &Values);
|
||||||
|
}
|
||||||
|
|
||||||
// Let's hope this can be done better when things have moved further ahead.
|
IDataBuffer* GetBuffer() const
|
||||||
// This really is not the best place to add something that depends on API behavior.
|
{
|
||||||
if (bind) mBuffer->BindBase();
|
// OpenGL needs to mess around with this in ways that should not be part of the interface.
|
||||||
|
return mBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() { return &Values; }
|
T *operator->() { return &Values; }
|
||||||
|
|
|
@ -44,7 +44,7 @@ FLightBuffer::FLightBuffer()
|
||||||
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs.
|
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs.
|
||||||
// We only want to disable using SSBOs for lights but not disable the feature entirely.
|
// We only want to disable using SSBOs for lights but not disable the feature entirely.
|
||||||
// Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD.
|
// Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD.
|
||||||
if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->gl_vendorstring, "Intel")))
|
if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel")))
|
||||||
{
|
{
|
||||||
mBufferType = true;
|
mBufferType = true;
|
||||||
mBlockAlign = 0;
|
mBlockAlign = 0;
|
||||||
|
@ -74,7 +74,6 @@ FLightBuffer::~FLightBuffer()
|
||||||
void FLightBuffer::Clear()
|
void FLightBuffer::Clear()
|
||||||
{
|
{
|
||||||
mIndex = 0;
|
mIndex = 0;
|
||||||
mLastMappedIndex = UINT_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLightBuffer::UploadLights(FDynLightData &data)
|
int FLightBuffer::UploadLights(FDynLightData &data)
|
||||||
|
@ -127,16 +126,13 @@ int FLightBuffer::UploadLights(FDynLightData &data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLightBuffer::DoBindUBO(unsigned int index)
|
int FLightBuffer::GetBinding(unsigned int index, size_t* pOffset, size_t* pSize)
|
||||||
{
|
{
|
||||||
// this function will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start.
|
// this function will only get called if a uniform buffer is used. For a shader storage buffer we only need to bind the buffer once at the start.
|
||||||
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
|
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
|
||||||
|
|
||||||
if (offset != mLastMappedIndex)
|
*pOffset = offset * ELEMENT_SIZE;
|
||||||
{
|
*pSize = mBlockSize * ELEMENT_SIZE;
|
||||||
mLastMappedIndex = offset;
|
|
||||||
mBuffer->BindRange(offset * ELEMENT_SIZE, mBlockSize * ELEMENT_SIZE);
|
|
||||||
}
|
|
||||||
return (index - offset);
|
return (index - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ class FLightBuffer
|
||||||
|
|
||||||
bool mBufferType;
|
bool mBufferType;
|
||||||
std::atomic<unsigned int> mIndex;
|
std::atomic<unsigned int> mIndex;
|
||||||
unsigned int mLastMappedIndex;
|
|
||||||
unsigned int mBlockAlign;
|
unsigned int mBlockAlign;
|
||||||
unsigned int mBlockSize;
|
unsigned int mBlockSize;
|
||||||
unsigned int mBufferSize;
|
unsigned int mBufferSize;
|
||||||
|
@ -34,32 +33,12 @@ public:
|
||||||
void Unmap() { mBuffer->Unmap(); }
|
void Unmap() { mBuffer->Unmap(); }
|
||||||
unsigned int GetBlockSize() const { return mBlockSize; }
|
unsigned int GetBlockSize() const { return mBlockSize; }
|
||||||
bool GetBufferType() const { return mBufferType; }
|
bool GetBufferType() const { return mBufferType; }
|
||||||
|
int GetBinding(unsigned int index, size_t* pOffset, size_t* pSize);
|
||||||
|
|
||||||
int DoBindUBO(unsigned int index);
|
// OpenGL needs the buffer to mess around with the binding.
|
||||||
|
IDataBuffer* GetBuffer() const
|
||||||
int ShaderIndex(unsigned int index) const
|
|
||||||
{
|
|
||||||
if (mBlockAlign == 0) return index;
|
|
||||||
// This must match the math in BindUBO.
|
|
||||||
unsigned int offset = (index / mBlockAlign) * mBlockAlign;
|
|
||||||
return int(index-offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only relevant for OpenGL, so this does not need access to the render state.
|
|
||||||
int BindUBO(int index)
|
|
||||||
{
|
{
|
||||||
if (!mBufferType && index > -1)
|
return mBuffer;
|
||||||
{
|
|
||||||
index = DoBindUBO(index);
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The parameter is a reminder for Vulkan.
|
|
||||||
void BindBase()
|
|
||||||
{
|
|
||||||
mBuffer->BindBase();
|
|
||||||
mLastMappedIndex = UINT_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -176,9 +176,6 @@ bool IShadowMap::PerformUpdate()
|
||||||
UpdateCycles.Clock();
|
UpdateCycles.Clock();
|
||||||
UploadAABBTree();
|
UploadAABBTree();
|
||||||
UploadLights();
|
UploadLights();
|
||||||
mLightList->BindBase();
|
|
||||||
mNodesBuffer->BindBase();
|
|
||||||
mLinesBuffer->BindBase();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -65,6 +65,8 @@ protected:
|
||||||
IShadowMap &operator=(IShadowMap &) = delete;
|
IShadowMap &operator=(IShadowMap &) = delete;
|
||||||
|
|
||||||
// OpenGL storage buffer with the list of lights in the shadow map texture
|
// OpenGL storage buffer with the list of lights in the shadow map texture
|
||||||
|
// These buffers need to be accessed by the OpenGL backend directly so that they can be bound.
|
||||||
|
public:
|
||||||
IDataBuffer *mLightList = nullptr;
|
IDataBuffer *mLightList = nullptr;
|
||||||
|
|
||||||
// OpenGL storage buffers for the AABB tree
|
// OpenGL storage buffers for the AABB tree
|
||||||
|
|
|
@ -468,7 +468,6 @@ void HWDrawInfo::RenderScene(FRenderState &state)
|
||||||
|
|
||||||
state.SetDepthMask(true);
|
state.SetDepthMask(true);
|
||||||
|
|
||||||
screen->mLights->BindBase();
|
|
||||||
state.EnableFog(true);
|
state.EnableFog(true);
|
||||||
state.SetRenderStyle(STYLE_Source);
|
state.SetRenderStyle(STYLE_Source);
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "r_renderer.h"
|
#include "r_renderer.h"
|
||||||
|
#include "atterm.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
FDynamicColormap NormalLight;
|
FDynamicColormap NormalLight;
|
||||||
|
|
|
@ -35,7 +35,7 @@ void VkPostprocess::SetActiveRenderTarget()
|
||||||
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
|
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
|
||||||
imageTransition.execute(fb->GetDrawCommands());
|
imageTransition.execute(fb->GetDrawCommands());
|
||||||
|
|
||||||
fb->GetRenderState()->SetRenderTarget(buffers->PipelineImage[mCurrentPipelineImage].View.get(), nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
|
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||||
|
@ -402,6 +402,18 @@ VkPPTexture::VkPPTexture(PPTexture *texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPPTexture::~VkPPTexture()
|
||||||
|
{
|
||||||
|
if (auto fb = GetVulkanFrameBuffer())
|
||||||
|
{
|
||||||
|
if (TexImage.Image) fb->FrameDeleteList.Images.push_back(std::move(TexImage.Image));
|
||||||
|
if (TexImage.View) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.View));
|
||||||
|
if (TexImage.DepthOnlyView) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.DepthOnlyView));
|
||||||
|
if (TexImage.PPFramebuffer) fb->FrameDeleteList.Framebuffers.push_back(std::move(TexImage.PPFramebuffer));
|
||||||
|
if (Staging) fb->FrameDeleteList.Buffers.push_back(std::move(Staging));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
VkPPShader::VkPPShader(PPShader *shader)
|
VkPPShader::VkPPShader(PPShader *shader)
|
||||||
|
@ -585,6 +597,7 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
|
||||||
VkTextureImage *tex = GetTexture(output.Type, output.Texture);
|
VkTextureImage *tex = GetTexture(output.Type, output.Texture);
|
||||||
|
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
|
std::unique_ptr<VulkanFramebuffer> *framebufferptr = nullptr;
|
||||||
int w, h;
|
int w, h;
|
||||||
if (tex)
|
if (tex)
|
||||||
{
|
{
|
||||||
|
@ -597,15 +610,17 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
|
||||||
view = tex->View->view;
|
view = tex->View->view;
|
||||||
w = tex->Image->width;
|
w = tex->Image->width;
|
||||||
h = tex->Image->height;
|
h = tex->Image->height;
|
||||||
|
framebufferptr = &tex->PPFramebuffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
|
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
|
||||||
|
framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex];
|
||||||
w = fb->swapChain->actualExtent.width;
|
w = fb->swapChain->actualExtent.width;
|
||||||
h = fb->swapChain->actualExtent.height;
|
h = fb->swapChain->actualExtent.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &framebuffer = passSetup->Framebuffers[view];
|
auto &framebuffer = *framebufferptr;
|
||||||
if (!framebuffer)
|
if (!framebuffer)
|
||||||
{
|
{
|
||||||
FramebufferBuilder builder;
|
FramebufferBuilder builder;
|
||||||
|
|
|
@ -88,6 +88,7 @@ class VkPPTexture : public PPTextureBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VkPPTexture(PPTexture *texture);
|
VkPPTexture(PPTexture *texture);
|
||||||
|
~VkPPTexture();
|
||||||
|
|
||||||
VkTextureImage TexImage;
|
VkTextureImage TexImage;
|
||||||
std::unique_ptr<VulkanBuffer> Staging;
|
std::unique_ptr<VulkanBuffer> Staging;
|
||||||
|
@ -103,7 +104,6 @@ public:
|
||||||
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
|
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
|
||||||
std::unique_ptr<VulkanRenderPass> RenderPass;
|
std::unique_ptr<VulkanRenderPass> RenderPass;
|
||||||
std::unique_ptr<VulkanPipeline> Pipeline;
|
std::unique_ptr<VulkanPipeline> Pipeline;
|
||||||
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffers;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateDescriptorLayout(const VkPPRenderPassKey &key);
|
void CreateDescriptorLayout(const VkPPRenderPassKey &key);
|
||||||
|
|
|
@ -59,7 +59,6 @@ public:
|
||||||
VkRenderPassKey PassKey;
|
VkRenderPassKey PassKey;
|
||||||
std::unique_ptr<VulkanRenderPass> RenderPasses[8];
|
std::unique_ptr<VulkanRenderPass> RenderPasses[8];
|
||||||
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
|
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
|
||||||
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffer;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);
|
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);
|
||||||
|
|
|
@ -528,11 +528,11 @@ void VkRenderState::EnableDrawBuffers(int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkRenderState::SetRenderTarget(VulkanImageView *view, VulkanImageView *depthStencilView, int width, int height, VkFormat format, VkSampleCountFlagBits samples)
|
void VkRenderState::SetRenderTarget(VkTextureImage *image, VulkanImageView *depthStencilView, int width, int height, VkFormat format, VkSampleCountFlagBits samples)
|
||||||
{
|
{
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
|
|
||||||
mRenderTarget.View = view;
|
mRenderTarget.Image = image;
|
||||||
mRenderTarget.DepthStencil = depthStencilView;
|
mRenderTarget.DepthStencil = depthStencilView;
|
||||||
mRenderTarget.Width = width;
|
mRenderTarget.Width = width;
|
||||||
mRenderTarget.Height = height;
|
mRenderTarget.Height = height;
|
||||||
|
@ -552,14 +552,14 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
|
||||||
|
|
||||||
mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key);
|
mPassSetup = fb->GetRenderPassManager()->GetRenderPass(key);
|
||||||
|
|
||||||
auto &framebuffer = mPassSetup->Framebuffer[mRenderTarget.View->view];
|
auto &framebuffer = mRenderTarget.Image->RSFramebuffers[key];
|
||||||
if (!framebuffer)
|
if (!framebuffer)
|
||||||
{
|
{
|
||||||
auto buffers = fb->GetBuffers();
|
auto buffers = fb->GetBuffers();
|
||||||
FramebufferBuilder builder;
|
FramebufferBuilder builder;
|
||||||
builder.setRenderPass(mPassSetup->GetRenderPass(0));
|
builder.setRenderPass(mPassSetup->GetRenderPass(0));
|
||||||
builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
|
builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
|
||||||
builder.addAttachment(mRenderTarget.View);
|
builder.addAttachment(mRenderTarget.Image->View.get());
|
||||||
if (key.DrawBuffers > 1)
|
if (key.DrawBuffers > 1)
|
||||||
builder.addAttachment(buffers->SceneFog.View.get());
|
builder.addAttachment(buffers->SceneFog.View.get());
|
||||||
if (key.DrawBuffers > 2)
|
if (key.DrawBuffers > 2)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "hwrenderer/textures/hw_material.h"
|
#include "hwrenderer/textures/hw_material.h"
|
||||||
|
|
||||||
class VkRenderPassSetup;
|
class VkRenderPassSetup;
|
||||||
|
class VkTextureImage;
|
||||||
|
|
||||||
class VkRenderState : public FRenderState
|
class VkRenderState : public FRenderState
|
||||||
{
|
{
|
||||||
|
@ -43,7 +44,7 @@ public:
|
||||||
void EnableDrawBuffers(int count) override;
|
void EnableDrawBuffers(int count) override;
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
void SetRenderTarget(VulkanImageView *view, VulkanImageView *depthStencilView, int width, int height, VkFormat Format, VkSampleCountFlagBits samples);
|
void SetRenderTarget(VkTextureImage *image, VulkanImageView *depthStencilView, int width, int height, VkFormat Format, VkSampleCountFlagBits samples);
|
||||||
void Bind(int bindingpoint, uint32_t offset);
|
void Bind(int bindingpoint, uint32_t offset);
|
||||||
void EndRenderPass();
|
void EndRenderPass();
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
|
@ -112,7 +113,7 @@ protected:
|
||||||
|
|
||||||
struct RenderTarget
|
struct RenderTarget
|
||||||
{
|
{
|
||||||
VulkanImageView *View = nullptr;
|
VkTextureImage *Image = nullptr;
|
||||||
VulkanImageView *DepthStencil = nullptr;
|
VulkanImageView *DepthStencil = nullptr;
|
||||||
int Width = 0;
|
int Width = 0;
|
||||||
int Height = 0;
|
int Height = 0;
|
||||||
|
|
|
@ -204,12 +204,9 @@ void VKVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t s
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void VKDataBuffer::BindRange(size_t start, size_t length)
|
|
||||||
|
void VKDataBuffer::BindRange(FRenderState* state, size_t start, size_t length)
|
||||||
{
|
{
|
||||||
GetVulkanFrameBuffer()->GetRenderState()->Bind(bindingpoint, (uint32_t)start);
|
static_cast<VkRenderState*>(state)->Bind(bindingpoint, (uint32_t)start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKDataBuffer::BindBase()
|
|
||||||
{
|
|
||||||
GetVulkanFrameBuffer()->GetRenderState()->Bind(bindingpoint, 0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -68,8 +68,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindRange(size_t start, size_t length) override;
|
void BindRange(FRenderState *state, size_t start, size_t length) override;
|
||||||
void BindBase() override;
|
|
||||||
|
|
||||||
int bindingpoint;
|
int bindingpoint;
|
||||||
};
|
};
|
||||||
|
|
|
@ -128,7 +128,14 @@ void VulkanFrameBuffer::InitializeState()
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_vendorstring = "Vulkan";
|
switch (device->PhysicalDevice.Properties.vendorID)
|
||||||
|
{
|
||||||
|
case 0x1002: vendorstring = "AMD"; break;
|
||||||
|
case 0x10DE: vendorstring = "NVIDIA"; break;
|
||||||
|
case 0x8086: vendorstring = "Intel"; break;
|
||||||
|
default: vendorstring = "Unknown"; break;
|
||||||
|
}
|
||||||
|
|
||||||
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
|
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
|
||||||
glslversion = 4.50f;
|
glslversion = 4.50f;
|
||||||
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
|
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
|
||||||
|
@ -145,7 +152,7 @@ void VulkanFrameBuffer::InitializeState()
|
||||||
|
|
||||||
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
||||||
mSkyData = new FSkyVertexBuffer;
|
mSkyData = new FSkyVertexBuffer;
|
||||||
mViewpoints = new GLViewpointBuffer;
|
mViewpoints = new HWViewpointBuffer;
|
||||||
mLights = new FLightBuffer();
|
mLights = new FLightBuffer();
|
||||||
|
|
||||||
CreateFanToTrisIndexBuffer();
|
CreateFanToTrisIndexBuffer();
|
||||||
|
@ -199,6 +206,7 @@ void VulkanFrameBuffer::DeleteFrameObjects()
|
||||||
{
|
{
|
||||||
FrameDeleteList.Images.clear();
|
FrameDeleteList.Images.clear();
|
||||||
FrameDeleteList.ImageViews.clear();
|
FrameDeleteList.ImageViews.clear();
|
||||||
|
FrameDeleteList.Framebuffers.clear();
|
||||||
FrameDeleteList.Buffers.clear();
|
FrameDeleteList.Buffers.clear();
|
||||||
FrameDeleteList.Descriptors.clear();
|
FrameDeleteList.Descriptors.clear();
|
||||||
FrameDeleteList.DescriptorPools.clear();
|
FrameDeleteList.DescriptorPools.clear();
|
||||||
|
@ -444,7 +452,7 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor *
|
||||||
|
|
||||||
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
|
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
|
||||||
{
|
{
|
||||||
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
||||||
bool useSSAO = (gl_ssao != 0);
|
bool useSSAO = (gl_ssao != 0);
|
||||||
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
|
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
|
||||||
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount());
|
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount());
|
||||||
|
@ -514,7 +522,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
|
||||||
barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||||
barrier0.execute(GetDrawCommands());
|
barrier0.execute(GetDrawCommands());
|
||||||
|
|
||||||
mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
|
mRenderState->SetRenderTarget(image, depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
|
||||||
|
|
||||||
IntRect bounds;
|
IntRect bounds;
|
||||||
bounds.left = bounds.top = 0;
|
bounds.left = bounds.top = 0;
|
||||||
|
@ -530,7 +538,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
|
||||||
barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||||
barrier1.execute(GetDrawCommands());
|
barrier1.execute(GetDrawCommands());
|
||||||
|
|
||||||
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
||||||
|
|
||||||
tex->SetUpdated(true);
|
tex->SetUpdated(true);
|
||||||
}
|
}
|
||||||
|
@ -709,11 +717,12 @@ void VulkanFrameBuffer::UpdatePalette()
|
||||||
|
|
||||||
FTexture *VulkanFrameBuffer::WipeStartScreen()
|
FTexture *VulkanFrameBuffer::WipeStartScreen()
|
||||||
{
|
{
|
||||||
const auto &viewport = screen->mScreenViewport;
|
SetViewportRects(nullptr);
|
||||||
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
|
|
||||||
|
auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
|
||||||
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
|
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
|
||||||
|
|
||||||
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen");
|
systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeStartScreen");
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
@ -724,11 +733,10 @@ FTexture *VulkanFrameBuffer::WipeEndScreen()
|
||||||
Draw2D();
|
Draw2D();
|
||||||
Clear2D();
|
Clear2D();
|
||||||
|
|
||||||
const auto &viewport = screen->mScreenViewport;
|
auto tex = new FWrapperTexture(mScreenViewport.width, mScreenViewport.height, 1);
|
||||||
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
|
|
||||||
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
|
auto systex = static_cast<VkHardwareTexture*>(tex->GetSystemTexture());
|
||||||
|
|
||||||
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen");
|
systex->CreateWipeTexture(mScreenViewport.width, mScreenViewport.height, "WipeEndScreen");
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
public:
|
public:
|
||||||
std::vector<std::unique_ptr<VulkanImage>> Images;
|
std::vector<std::unique_ptr<VulkanImage>> Images;
|
||||||
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
|
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
|
||||||
|
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
|
||||||
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
|
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
|
||||||
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
|
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
|
||||||
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;
|
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;
|
||||||
|
|
|
@ -207,6 +207,7 @@ bool VulkanSwapChain::CreateSwapChain(VkSwapchainKHR oldSwapChain)
|
||||||
|
|
||||||
void VulkanSwapChain::CreateViews()
|
void VulkanSwapChain::CreateViews()
|
||||||
{
|
{
|
||||||
|
framebuffers.resize(swapChainImages.size());
|
||||||
swapChainImageViews.reserve(swapChainImages.size());
|
swapChainImageViews.reserve(swapChainImages.size());
|
||||||
for (size_t i = 0; i < swapChainImages.size(); i++)
|
for (size_t i = 0; i < swapChainImages.size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -335,6 +336,7 @@ void VulkanSwapChain::GetImages()
|
||||||
|
|
||||||
void VulkanSwapChain::ReleaseViews()
|
void VulkanSwapChain::ReleaseViews()
|
||||||
{
|
{
|
||||||
|
framebuffers.clear();
|
||||||
for (auto &view : swapChainImageViews)
|
for (auto &view : swapChainImageViews)
|
||||||
{
|
{
|
||||||
vkDestroyImageView(device->device, view, nullptr);
|
vkDestroyImageView(device->device, view, nullptr);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
class VulkanSemaphore;
|
class VulkanSemaphore;
|
||||||
class VulkanFence;
|
class VulkanFence;
|
||||||
|
class VulkanFramebuffer;
|
||||||
|
|
||||||
class VulkanSwapChain
|
class VulkanSwapChain
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,7 @@ public:
|
||||||
|
|
||||||
std::vector<VkImage> swapChainImages;
|
std::vector<VkImage> swapChainImages;
|
||||||
std::vector<VkImageView> swapChainImageViews;
|
std::vector<VkImageView> swapChainImageViews;
|
||||||
|
std::vector<std::unique_ptr<VulkanFramebuffer>> framebuffers;
|
||||||
|
|
||||||
VkExtent2D actualExtent;
|
VkExtent2D actualExtent;
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,10 @@ void VkHardwareTexture::Reset()
|
||||||
auto &deleteList = fb->FrameDeleteList;
|
auto &deleteList = fb->FrameDeleteList;
|
||||||
if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
|
if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
|
||||||
if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View));
|
if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View));
|
||||||
|
for (auto &it : mImage.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
|
||||||
if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
|
if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
|
||||||
if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View));
|
if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View));
|
||||||
|
for (auto &it : mDepthStencil.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
|
||||||
mImage.reset();
|
mImage.reset();
|
||||||
mDepthStencil.reset();
|
mDepthStencil.reset();
|
||||||
}
|
}
|
||||||
|
@ -374,5 +376,33 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
|
||||||
mImage.View = viewbuilder.create(fb->device);
|
mImage.View = viewbuilder.create(fb->device);
|
||||||
mImage.View->SetDebugName(name);
|
mImage.View->SetDebugName(name);
|
||||||
|
|
||||||
fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
if (fb->GetBuffers()->GetWidth() > 0 && fb->GetBuffers()->GetHeight() > 0)
|
||||||
|
{
|
||||||
|
fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// hwrenderer asked image data from a frame buffer that was never written into. Let's give it that..
|
||||||
|
// (ideally the hwrenderer wouldn't do this, but the calling code is too complex for me to fix)
|
||||||
|
|
||||||
|
VkImageTransition transition0;
|
||||||
|
transition0.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||||
|
transition0.execute(fb->GetTransferCommands());
|
||||||
|
|
||||||
|
VkImageSubresourceRange range = {};
|
||||||
|
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
range.layerCount = 1;
|
||||||
|
range.levelCount = 1;
|
||||||
|
|
||||||
|
VkClearColorValue value = {};
|
||||||
|
value.float32[0] = 0.0f;
|
||||||
|
value.float32[1] = 0.0f;
|
||||||
|
value.float32[2] = 0.0f;
|
||||||
|
value.float32[3] = 1.0f;
|
||||||
|
fb->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range);
|
||||||
|
|
||||||
|
VkImageTransition transition1;
|
||||||
|
transition1.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||||
|
transition1.execute(fb->GetTransferCommands());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "vulkan/system/vk_objects.h"
|
#include "vulkan/system/vk_objects.h"
|
||||||
#include "vulkan/system/vk_builders.h"
|
#include "vulkan/system/vk_builders.h"
|
||||||
|
#include "vulkan/renderer/vk_renderpass.h"
|
||||||
|
|
||||||
class VkTextureImage
|
class VkTextureImage
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,8 @@ public:
|
||||||
std::unique_ptr<VulkanImageView> DepthOnlyView;
|
std::unique_ptr<VulkanImageView> DepthOnlyView;
|
||||||
VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
std::unique_ptr<VulkanFramebuffer> PPFramebuffer;
|
||||||
|
std::map<VkRenderPassKey, std::unique_ptr<VulkanFramebuffer>> RSFramebuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VkImageTransition
|
class VkImageTransition
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "r_data/sprites.h"
|
#include "r_data/sprites.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "dobject.h"
|
#include "dobject.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ static const FLOP FxFlops[] =
|
||||||
{ NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } },
|
{ NAME_CosH, FLOP_COSH, [](double v) { return g_cosh(v); } },
|
||||||
{ NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } },
|
{ NAME_SinH, FLOP_SINH, [](double v) { return g_sinh(v); } },
|
||||||
{ NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } },
|
{ NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } },
|
||||||
|
|
||||||
|
{ NAME_Round, FLOP_ROUND, [](double v) { return round(v); } },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -4835,7 +4837,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
// If this is a local variable we need another register for the result.
|
// If this is a local variable we need another register for the result.
|
||||||
if (trueop.Fixed)
|
if (trueop.Fixed)
|
||||||
{
|
{
|
||||||
out = ExpEmit(build, trueop.RegType);
|
out = ExpEmit(build, trueop.RegType, trueop.RegCount);
|
||||||
build->Emit(truex->ValueType->GetMoveOp(), out.RegNum, trueop.RegNum, 0);
|
build->Emit(truex->ValueType->GetMoveOp(), out.RegNum, trueop.RegNum, 0);
|
||||||
}
|
}
|
||||||
else out = trueop;
|
else out = trueop;
|
||||||
|
@ -6127,18 +6129,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
if (sym->mVersion <= ctx.Version)
|
if (sym->mVersion <= ctx.Version)
|
||||||
{
|
{
|
||||||
if (!(ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0)
|
// Allow use of deprecated symbols in deprecated functions of the internal code. This is meant to allow deprecated code to remain as it was,
|
||||||
{
|
// even if it depends on some deprecated symbol.
|
||||||
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated global variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
|
// The main motivation here is to keep the deprecated static functions accessing the global level variable as they were.
|
||||||
}
|
// Print these only if debug output is active and at the highest verbosity level.
|
||||||
else
|
const bool internal = (ctx.Function->Variants[0].Flags & VARF_Deprecated) && Wads.GetLumpFile(ctx.Lump) == 0;
|
||||||
{
|
|
||||||
// Allow use of deprecated symbols in deprecated functions of the internal code. This is meant to allow deprecated code to remain as it was,
|
ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING,
|
||||||
// even if it depends on some deprecated symbol.
|
"%sAccessing deprecated global variable %s - deprecated since %d.%d.%d", internal ? TEXTCOLOR_BLUE : "",
|
||||||
// The main motivation here is to keep the deprecated static functions accessing the global level variable as they were.
|
sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
|
||||||
// Print these only if debug output is active and at the highest verbosity level.
|
|
||||||
ScriptPosition.Message(MSG_DEBUGMSG, TEXTCOLOR_BLUE "Accessing deprecated global variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7425,7 +7424,6 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
|
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
|
||||||
|
|
||||||
arrayvar.Free(build);
|
|
||||||
start = ExpEmit(build, REGT_POINTER);
|
start = ExpEmit(build, REGT_POINTER);
|
||||||
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
|
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
|
||||||
|
|
||||||
|
@ -7445,18 +7443,18 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
arraymemberbase->membervar = origmembervar;
|
arraymemberbase->membervar = origmembervar;
|
||||||
arraymemberbase->AddressRequested = origaddrreq;
|
arraymemberbase->AddressRequested = origaddrreq;
|
||||||
Array->ValueType = origvaluetype;
|
Array->ValueType = origvaluetype;
|
||||||
|
|
||||||
|
arrayvar.Free(build);
|
||||||
}
|
}
|
||||||
else if (Array->ExprType == EFX_ArrayElement && Array->isStaticArray())
|
else if (Array->ExprType == EFX_ArrayElement && Array->isStaticArray())
|
||||||
{
|
{
|
||||||
bool ismeta = Array->ExprType == EFX_ClassMember && static_cast<FxClassMember*>(Array)->membervar->Flags & VARF_Meta;
|
bound = ExpEmit(build, REGT_INT);
|
||||||
|
build->Emit(OP_LW, bound.RegNum, arrayvar.RegNum, build->GetConstantInt(myoffsetof(FArray, Count)));
|
||||||
|
|
||||||
arrayvar.Free(build);
|
arrayvar.Free(build);
|
||||||
start = ExpEmit(build, REGT_POINTER);
|
start = ExpEmit(build, REGT_POINTER);
|
||||||
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
|
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
|
||||||
|
|
||||||
bound = ExpEmit(build, REGT_INT);
|
|
||||||
build->Emit(OP_LW, bound.RegNum, arrayvar.RegNum, build->GetConstantInt(sizeof(void*)));
|
|
||||||
|
|
||||||
nestedarray = true;
|
nestedarray = true;
|
||||||
}
|
}
|
||||||
else start = arrayvar;
|
else start = arrayvar;
|
||||||
|
@ -7514,7 +7512,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpEmit indexv(index->Emit(build));
|
ExpEmit indexv(index->Emit(build));
|
||||||
if (SizeAddr != ~0u)
|
if (SizeAddr != ~0u || nestedarray)
|
||||||
{
|
{
|
||||||
build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum);
|
build->Emit(OP_BOUND_R, indexv.RegNum, bound.RegNum);
|
||||||
bound.Free(build);
|
bound.Free(build);
|
||||||
|
@ -11352,8 +11350,59 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
if (RegNum == -1)
|
if (RegNum == -1)
|
||||||
{
|
{
|
||||||
if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount);
|
if (!(VarFlags & VARF_Out))
|
||||||
else RegNum = build->Registers[REGT_POINTER].Get(1);
|
{
|
||||||
|
const int regType = ValueType->GetRegType();
|
||||||
|
assert(regType <= REGT_TYPE);
|
||||||
|
|
||||||
|
auto& registers = build->Registers[regType];
|
||||||
|
RegNum = registers.Get(RegCount);
|
||||||
|
|
||||||
|
// Check for reused registers and clean them if needed
|
||||||
|
bool useDirtyRegisters = false;
|
||||||
|
|
||||||
|
for (int reg = RegNum, end = RegNum + RegCount; reg < end; ++reg)
|
||||||
|
{
|
||||||
|
if (!registers.IsDirty(reg))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
useDirtyRegisters = true;
|
||||||
|
|
||||||
|
switch (regType)
|
||||||
|
{
|
||||||
|
case REGT_INT:
|
||||||
|
build->Emit(OP_LI, reg, 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_FLOAT:
|
||||||
|
build->Emit(OP_LKF, reg, build->GetConstantFloat(0.0));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_STRING:
|
||||||
|
build->Emit(OP_LKS, reg, build->GetConstantString(nullptr));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_POINTER:
|
||||||
|
build->Emit(OP_LKP, reg, build->GetConstantAddress(nullptr));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useDirtyRegisters)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_DEBUGMSG, "Implicit initialization of variable %s", Name.GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RegNum = build->Registers[REGT_POINTER].Get(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -783,7 +783,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Find, ArrayFind<FDynArray_Obj COMMA
|
||||||
|
|
||||||
int ObjArrayPush(FDynArray_Obj *self, DObject *obj)
|
int ObjArrayPush(FDynArray_Obj *self, DObject *obj)
|
||||||
{
|
{
|
||||||
if (self == nullptr) NullParam("\"self\"");
|
|
||||||
GC::WriteBarrier(obj);
|
GC::WriteBarrier(obj);
|
||||||
return self->Push(obj);
|
return self->Push(obj);
|
||||||
}
|
}
|
||||||
|
@ -812,7 +811,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(FDynArray_Obj, Delete, ArrayDelete<FDynArray_Obj>)
|
||||||
|
|
||||||
void ObjArrayInsert(FDynArray_Obj *self,int index, DObject *obj)
|
void ObjArrayInsert(FDynArray_Obj *self,int index, DObject *obj)
|
||||||
{
|
{
|
||||||
if (self == nullptr) NullParam("\"self\"");
|
|
||||||
GC::WriteBarrier(obj);
|
GC::WriteBarrier(obj);
|
||||||
self->Insert(index, obj);
|
self->Insert(index, obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,6 +367,7 @@ void VMFunctionBuilder::ParamChange(int delta)
|
||||||
VMFunctionBuilder::RegAvailability::RegAvailability()
|
VMFunctionBuilder::RegAvailability::RegAvailability()
|
||||||
{
|
{
|
||||||
memset(Used, 0, sizeof(Used));
|
memset(Used, 0, sizeof(Used));
|
||||||
|
memset(Dirty, 0, sizeof(Dirty));
|
||||||
MostUsed = 0;
|
MostUsed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,16 +494,19 @@ void VMFunctionBuilder::RegAvailability::Return(int reg, int count)
|
||||||
// because for that case it pushes the self pointer a second time without reallocating, so it gets freed twice.
|
// because for that case it pushes the self pointer a second time without reallocating, so it gets freed twice.
|
||||||
//assert((Used[firstword] & mask) == mask);
|
//assert((Used[firstword] & mask) == mask);
|
||||||
Used[firstword] &= ~mask;
|
Used[firstword] &= ~mask;
|
||||||
|
Dirty[firstword] |= mask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Range is in two words.
|
{ // Range is in two words.
|
||||||
partialmask = mask << firstbit;
|
partialmask = mask << firstbit;
|
||||||
assert((Used[firstword] & partialmask) == partialmask);
|
assert((Used[firstword] & partialmask) == partialmask);
|
||||||
Used[firstword] &= ~partialmask;
|
Used[firstword] &= ~partialmask;
|
||||||
|
Dirty[firstword] |= partialmask;
|
||||||
|
|
||||||
partialmask = mask >> (32 - firstbit);
|
partialmask = mask >> (32 - firstbit);
|
||||||
assert((Used[firstword + 1] & partialmask) == partialmask);
|
assert((Used[firstword + 1] & partialmask) == partialmask);
|
||||||
Used[firstword + 1] &= ~partialmask;
|
Used[firstword + 1] &= ~partialmask;
|
||||||
|
Dirty[firstword + 1] |= partialmask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,16 @@ public:
|
||||||
void Return(int reg, int count);
|
void Return(int reg, int count);
|
||||||
bool Reuse(int regnum);
|
bool Reuse(int regnum);
|
||||||
|
|
||||||
|
bool IsDirty(int reg) const
|
||||||
|
{
|
||||||
|
const int firstword = reg / 32;
|
||||||
|
const int firstbit = reg & 31;
|
||||||
|
return Dirty[firstword] & (1 << firstbit);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
|
VM_UWORD Used[256/32]; // Bitmap of used registers (bit set means reg is used)
|
||||||
|
VM_UWORD Dirty[256/32];
|
||||||
int MostUsed;
|
int MostUsed;
|
||||||
|
|
||||||
friend class VMFunctionBuilder;
|
friend class VMFunctionBuilder;
|
||||||
|
|
|
@ -181,6 +181,8 @@ static const char *const FlopNames[] =
|
||||||
"cosh",
|
"cosh",
|
||||||
"sinh",
|
"sinh",
|
||||||
"tanh",
|
"tanh",
|
||||||
|
|
||||||
|
"round",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const VMScriptFunction *func);
|
static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const VMScriptFunction *func);
|
||||||
|
|
|
@ -1148,6 +1148,7 @@ static void ParseActor(FScanner &sc, PNamespace *ns)
|
||||||
bag.Namespace = ns;
|
bag.Namespace = ns;
|
||||||
bag.Version = { 2, 0, 0 };
|
bag.Version = { 2, 0, 0 };
|
||||||
bag.fromDecorate = true;
|
bag.fromDecorate = true;
|
||||||
|
bag.ScriptPosition = sc;
|
||||||
info = ParseActorHeader(sc, &bag);
|
info = ParseActorHeader(sc, &bag);
|
||||||
sc.MustGetToken('{');
|
sc.MustGetToken('{');
|
||||||
while (sc.MustGetAnyToken(), sc.TokenType != '}')
|
while (sc.MustGetAnyToken(), sc.TokenType != '}')
|
||||||
|
|
|
@ -323,6 +323,28 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
|
||||||
I_Error("Native direct member function calls not implemented\n");
|
I_Error("Native direct member function calls not implemented\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target->ImplicitArgs > 0)
|
||||||
|
{
|
||||||
|
auto label = EmitThrowExceptionLabel(X_READ_NIL);
|
||||||
|
|
||||||
|
assert(ParamOpcodes.Size() > 0);
|
||||||
|
const VMOP *param = ParamOpcodes[0];
|
||||||
|
const int bc = param->i16u;
|
||||||
|
asmjit::X86Gp *reg = nullptr;
|
||||||
|
|
||||||
|
switch (param->a & REGT_TYPE)
|
||||||
|
{
|
||||||
|
case REGT_STRING: reg = ®S[bc]; break;
|
||||||
|
case REGT_POINTER: reg = ®A[bc]; break;
|
||||||
|
default:
|
||||||
|
I_Error("Unexpected register type for self pointer\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cc.test(*reg, *reg);
|
||||||
|
cc.jz(label);
|
||||||
|
}
|
||||||
|
|
||||||
asmjit::CBNode *cursorBefore = cc.getCursor();
|
asmjit::CBNode *cursorBefore = cc.getCursor();
|
||||||
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature());
|
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature());
|
||||||
call->setInlineComment(target->PrintableName.GetChars());
|
call->setInlineComment(target->PrintableName.GetChars());
|
||||||
|
|
|
@ -985,6 +985,7 @@ void JitCompiler::EmitFLOP()
|
||||||
case FLOP_COSH: func = g_cosh; break;
|
case FLOP_COSH: func = g_cosh; break;
|
||||||
case FLOP_SINH: func = g_sinh; break;
|
case FLOP_SINH: func = g_sinh; break;
|
||||||
case FLOP_TANH: func = g_tanh; break;
|
case FLOP_TANH: func = g_tanh; break;
|
||||||
|
case FLOP_ROUND: func = round; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = newResultXmmSd();
|
auto result = newResultXmmSd();
|
||||||
|
|
|
@ -1741,6 +1741,8 @@ static double DoFLOP(int flop, double v)
|
||||||
case FLOP_COSH: return g_cosh(v);
|
case FLOP_COSH: return g_cosh(v);
|
||||||
case FLOP_SINH: return g_sinh(v);
|
case FLOP_SINH: return g_sinh(v);
|
||||||
case FLOP_TANH: return g_tanh(v);
|
case FLOP_TANH: return g_tanh(v);
|
||||||
|
|
||||||
|
case FLOP_ROUND: return round(v);
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -101,6 +101,8 @@ enum
|
||||||
FLOP_COSH,
|
FLOP_COSH,
|
||||||
FLOP_SINH,
|
FLOP_SINH,
|
||||||
FLOP_TANH,
|
FLOP_TANH,
|
||||||
|
|
||||||
|
FLOP_ROUND,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cast operations
|
// Cast operations
|
||||||
|
|
|
@ -1353,7 +1353,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
|
||||||
// This is a global variable.
|
// This is a global variable.
|
||||||
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
|
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
|
||||||
PField *f = Create<PField>(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue);
|
PField *f = Create<PField>(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue);
|
||||||
if (f->Flags & (ZCC_Version | ZCC_Deprecated))
|
if (field->Flags & (ZCC_Version | ZCC_Deprecated))
|
||||||
{
|
{
|
||||||
f->mVersion = field->Version;
|
f->mVersion = field->Version;
|
||||||
}
|
}
|
||||||
|
|
|
@ -933,7 +933,8 @@ void pre_resample(Sample * sp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = newdata = (sample_t *)safe_malloc((int32_t)(newlen >> (FRACTION_BITS - 1)) + 2);
|
// [EP] Fix the bad allocation count.
|
||||||
|
dest = newdata = (sample_t *)safe_malloc(((int32_t)(newlen >> (FRACTION_BITS - 1)) + 2)*sizeof(sample_t));
|
||||||
dest[newlen >> FRACTION_BITS] = 0;
|
dest[newlen >> FRACTION_BITS] = 0;
|
||||||
|
|
||||||
*dest++ = src[0];
|
*dest++ = src[0];
|
||||||
|
|
97
src/utility/atterm.cpp
Normal file
97
src/utility/atterm.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
** attern.cpp
|
||||||
|
** Termination handling
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 1998-2007 Randy Heit
|
||||||
|
** Copyright 2019 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "atterm.h"
|
||||||
|
|
||||||
|
static TArray<std::pair<void (*)(void), const char *>> TermFuncs;
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// atterm
|
||||||
|
//
|
||||||
|
// Our own atexit because atexit can be problematic under Linux, though I
|
||||||
|
// forget the circumstances that cause trouble.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void addterm(void (*func)(), const char *name)
|
||||||
|
{
|
||||||
|
// Make sure this function wasn't already registered.
|
||||||
|
|
||||||
|
for (auto &term : TermFuncs)
|
||||||
|
{
|
||||||
|
if (term.first == func)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TermFuncs.Push(std::make_pair(func, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// call_terms
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void call_terms()
|
||||||
|
{
|
||||||
|
for(int i = TermFuncs.Size()-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
TermFuncs[i].first();
|
||||||
|
}
|
||||||
|
TermFuncs.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// popterm
|
||||||
|
//
|
||||||
|
// Removes the most recently register atterm function.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void popterm()
|
||||||
|
{
|
||||||
|
if (TermFuncs.Size() > 0)
|
||||||
|
{
|
||||||
|
TermFuncs.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
6
src/utility/atterm.h
Normal file
6
src/utility/atterm.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void addterm (void (*func)(void), const char *name);
|
||||||
|
#define atterm(t) addterm (t, #t)
|
||||||
|
void popterm ();
|
||||||
|
void call_terms();
|
|
@ -86,6 +86,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.8: June, 2000
|
Cephes Math Library Release 2.8: June, 2000
|
||||||
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mconf.h"
|
#include "mconf.h"
|
||||||
|
|
|
@ -70,6 +70,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.8: June, 2000
|
Cephes Math Library Release 2.8: June, 2000
|
||||||
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.3: March, 1995
|
Cephes Math Library Release 2.3: March, 1995
|
||||||
Copyright 1984, 1995 by Stephen L. Moshier
|
Copyright 1984, 1995 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mconf.h"
|
#include "mconf.h"
|
||||||
|
|
|
@ -42,6 +42,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.8: June, 2000
|
Cephes Math Library Release 2.8: June, 2000
|
||||||
Copyright 1985, 1995, 2000 by Stephen L. Moshier
|
Copyright 1985, 1995, 2000 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mconf.h"
|
#include "mconf.h"
|
||||||
|
|
|
@ -57,6 +57,31 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.2: January, 1991
|
Cephes Math Library Release 2.2: January, 1991
|
||||||
Copyright 1984, 1991 by Stephen L. Moshier
|
Copyright 1984, 1991 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.3: March, 1995
|
Cephes Math Library Release 2.3: March, 1995
|
||||||
Copyright 1984, 1995 by Stephen L. Moshier
|
Copyright 1984, 1995 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.8: June, 2000
|
Cephes Math Library Release 2.8: June, 2000
|
||||||
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mconf.h"
|
#include "mconf.h"
|
||||||
|
|
|
@ -44,6 +44,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.8: June, 2000
|
Cephes Math Library Release 2.8: June, 2000
|
||||||
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mconf.h"
|
#include "mconf.h"
|
||||||
|
|
|
@ -59,6 +59,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.3: June, 1995
|
Cephes Math Library Release 2.3: June, 1995
|
||||||
Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier
|
Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,31 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.0: April, 1987
|
Cephes Math Library Release 2.0: April, 1987
|
||||||
Copyright 1984, 1987 by Stephen L. Moshier
|
Copyright 1984, 1987 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,31 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.1: December, 1988
|
Cephes Math Library Release 2.1: December, 1988
|
||||||
Copyright 1984, 1987, 1988 by Stephen L. Moshier
|
Copyright 1984, 1987, 1988 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,30 @@
|
||||||
/*
|
/*
|
||||||
Cephes Math Library Release 2.8: June, 2000
|
Cephes Math Library Release 2.8: June, 2000
|
||||||
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
Copyright 1984, 1995, 2000 by Stephen L. Moshier
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the <ORGANIZATION> nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue