Merge remote-tracking branch 'gzdoom/master' into qz-master-2022-05-10

This commit is contained in:
Major Cooke 2022-05-21 10:22:06 -05:00
commit e9692781a9
40 changed files with 345 additions and 136 deletions

View file

@ -55,11 +55,11 @@ body:
validations:
required: false
- type: input
id: other
id: os_detail
attributes:
label: If Other OS, please describe
label: Please describe your specific OS version
description: Other details
placeholder: "Windows, Mac OSX version, Debian, Ubuntu, Arch, etc."
placeholder: "Windows 11 Home/Pro/Server/etc, Mac OSX version, Debian 10/11/etc, Ubuntu 18/20/etc, Arch, etc."
validations:
required: false
- type: input

Binary file not shown.

View file

@ -403,7 +403,10 @@ if( MSVC AND NOT VPX_FOUND )
# Use prebuilt library
set( VPX_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/Windows/vpx" )
set( VPX_INCLUDE_DIR ${VPX_ROOT_PATH}/include )
set( VPX_LIBRARIES libvpx libcompat-to-msvc )
set( VPX_LIBRARIES libvpx )
if ( NOT ARM64 )
set (VPX_LIBRARIES ${VPX_LIBRARIES} libcompat-to-msvc )
endif()
if( ARM64 )
link_directories( ${VPX_ROOT_PATH}/lib/arm64 )
elseif( X64 )

View file

@ -222,7 +222,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
return false;
}
NumLumps = info.NumEntries;
NumLumps = (uint32_t)info.NumEntries;
dirsize = info.DirectorySize;
DirectoryOffset = info.DirectoryOffset;
}
@ -521,7 +521,7 @@ int FZipLump::GetFileOffset()
{
if (Method != METHOD_STORED) return -1;
if (NeedFileStart) SetLumpAddress();
return Position;
return (int)Position;
}
//==========================================================================

View file

@ -277,7 +277,7 @@ void MarkArray(DObject **obj, size_t count)
static size_t CalcStepSize()
{
int time_passed = CheckTime - LastCollectTime;
int time_passed = int(CheckTime - LastCollectTime);
auto alloc = min(LastCollectAlloc, Estimate);
size_t bytes_gained = AllocBytes > alloc ? AllocBytes - alloc : 0;
return (StepMul > 0 && time_passed > 0)
@ -390,7 +390,7 @@ static size_t SingleStep()
case GCS_Finalize:
State = GCS_Pause; // end collection
LastCollectAlloc = AllocBytes;
LastCollectTime = CheckTime;
LastCollectTime = (int)CheckTime;
return 0;
default:

View file

@ -561,6 +561,11 @@ void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash,
GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D);
}
bool OpenGLFrameBuffer::CompileNextShader()
{
return GLRenderer->mShaderManager->CompileNextShader();
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeStartScreen

View file

@ -23,7 +23,7 @@ public:
explicit OpenGLFrameBuffer() {}
OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ;
~OpenGLFrameBuffer();
bool CompileNextShader() override;
void InitializeState() override;
void Update() override;

View file

@ -672,7 +672,7 @@ bool FShader::Bind()
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType)
{
FString defines;
defines += shaderdefines;
if (shaderdefines) defines += shaderdefines;
// this can't be in the shader code due to ATI strangeness.
if (!usediscard) defines += "#define NO_ALPHATEST\n";
if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n";
@ -707,6 +707,20 @@ FShaderManager::FShaderManager()
mPassShaders.Push(new FShaderCollection((EPassType)passType));
}
bool FShaderManager::CompileNextShader()
{
if (mPassShaders[mCompilePass]->CompileNextShader())
{
mCompilePass++;
if (mCompilePass >= MAX_PASS_TYPES)
{
mCompilePass = -1;
return true;
}
}
return false;
}
FShaderManager::~FShaderManager()
{
glUseProgram(0);
@ -727,7 +741,7 @@ void FShaderManager::SetActiveShader(FShader *sh)
FShader *FShaderManager::BindEffect(int effect, EPassType passType)
{
if (passType < mPassShaders.Size())
if (passType < mPassShaders.Size() && mCompilePass == -1)
return mPassShaders[passType]->BindEffect(effect);
else
return nullptr;
@ -735,7 +749,11 @@ FShader *FShaderManager::BindEffect(int effect, EPassType passType)
FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
{
if (r_skipmats && eff >= 3 && eff <= 4)
if (mCompilePass > -1)
{
return mPassShaders[0]->Get(0, false);
}
if ((r_skipmats && eff >= 3 && eff <= 4))
eff = 0;
if (passType < mPassShaders.Size())
@ -752,7 +770,14 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT
FShaderCollection::FShaderCollection(EPassType passType)
{
CompileShaders(passType);
mPassType = passType;
mMaterialShaders.Clear();
mMaterialShadersNAT.Clear();
for (int i = 0; i < MAX_EFFECTS; i++)
{
mEffectShaders[i] = NULL;
}
CompileNextShader();
}
//==========================================================================
@ -772,35 +797,47 @@ FShaderCollection::~FShaderCollection()
//
//==========================================================================
void FShaderCollection::CompileShaders(EPassType passType)
bool FShaderCollection::CompileNextShader()
{
mMaterialShaders.Clear();
mMaterialShadersNAT.Clear();
for (int i = 0; i < MAX_EFFECTS; i++)
int i = mCompileIndex;
if (mCompileState == 0)
{
mEffectShaders[i] = NULL;
}
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
{
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType);
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, mPassType);
mMaterialShaders.Push(shc);
if (i < SHADER_NoTexture)
mCompileIndex++;
if (defaultshaders[mCompileIndex].ShaderName == nullptr)
{
FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType);
mMaterialShadersNAT.Push(shc1);
mCompileIndex = 0;
mCompileState++;
}
}
for(unsigned i = 0; i < usershaders.Size(); i++)
else if (mCompileState == 1)
{
FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, mPassType);
mMaterialShadersNAT.Push(shc1);
mCompileIndex++;
if (mCompileIndex >= SHADER_NoTexture)
{
mCompileIndex = 0;
mCompileState++;
if (usershaders.Size() == 0) mCompileState++;
}
}
else if (mCompileState == 2)
{
FString name = ExtractFileBase(usershaders[i].shader);
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, passType);
FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, mPassType);
mMaterialShaders.Push(shc);
mCompileIndex++;
if (mCompileIndex >= (int)usershaders.Size())
{
mCompileIndex = 0;
mCompileState++;
}
}
for(int i=0;i<MAX_EFFECTS;i++)
else if (mCompileState == 3)
{
FShader *eff = new FShader(effectshaders[i].ShaderName);
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
@ -809,7 +846,13 @@ void FShaderCollection::CompileShaders(EPassType passType)
delete eff;
}
else mEffectShaders[i] = eff;
mCompileIndex++;
if (mCompileIndex >= MAX_EFFECTS)
{
return true;
}
}
return false;
}
//==========================================================================

View file

@ -309,10 +309,12 @@ public:
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
void SetActiveShader(FShader *sh);
bool CompileNextShader();
private:
FShader *mActiveShader = nullptr;
TArray<FShaderCollection*> mPassShaders;
int mCompilePass = 0;
friend class FShader;
};
@ -322,21 +324,23 @@ class FShaderCollection
TArray<FShader*> mMaterialShaders;
TArray<FShader*> mMaterialShadersNAT;
FShader *mEffectShaders[MAX_EFFECTS];
int mCompileState = 0, mCompileIndex = 0;
EPassType mPassType;
void Clean();
void CompileShaders(EPassType passType);
public:
FShaderCollection(EPassType passType);
~FShaderCollection();
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
int Find(const char *mame);
bool CompileNextShader();
FShader *BindEffect(int effect);
FShader *Get(unsigned int eff, bool alphateston)
{
// indices 0-2 match the warping modes, 3 no texture, the following are custom
if (!alphateston && eff <= 2)
if (!alphateston && eff < SHADER_NoTexture)
{
return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
}

View file

@ -26,6 +26,7 @@ public:
void InitializeState() override;
void Update() override;
int GetShaderCount() override { return 0; }
void FirstEye() override;
void NextEye(int eyecount) override;

View file

@ -733,7 +733,7 @@ bool FShader::Bind(ShaderFlavourData& flavour)
//==========================================================================
//
// Since all shaders are REQUIRED, any error here needs to be fatal
//
//
//==========================================================================
@ -744,21 +744,8 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
// this can't be in the shader code due to ATI strangeness.
if (!usediscard) defines += "#define NO_ALPHATEST\n";
FShader *shader = NULL;
try
{
shader = new FShader(ShaderName);
if (!shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()))
{
I_FatalError("Unable to load shader %s\n", ShaderName);
}
}
catch(CRecoverableError &err)
{
if (shader != NULL) delete shader;
shader = NULL;
I_FatalError("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage());
}
FShader *shader = new FShader(ShaderName);
shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars());
return shader;
}

View file

@ -34,7 +34,11 @@
*/
#include "cmdlib.h"
#include "hw_shaderpatcher.h"
#include "textures.h"
#include "hw_renderstate.h"
#include "v_video.h"
static bool IsGlslWhitespace(char c)
@ -296,3 +300,12 @@ const FEffectShader effectshaders[] =
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
};
int DFrameBuffer::GetShaderCount()
{
int i;
for (i = 0; defaultshaders[i].ShaderName != nullptr; i++);
return MAX_PASS_TYPES * (countof(defaultshaders) - 1 + usershaders.Size() + MAX_EFFECTS + SHADER_NoTexture);
}

View file

@ -28,3 +28,4 @@ struct FEffectShader
extern const FDefaultShader defaultshaders[];
extern const FEffectShader effectshaders[];

View file

@ -26,6 +26,7 @@ public:
PolyFrameBuffer(void *hMonitor, bool fullscreen);
~PolyFrameBuffer();
int GetShaderCount() override { return 0; }
void Update() override;

View file

@ -158,6 +158,8 @@ public:
virtual void InitializeState() = 0; // For stuff that needs 'screen' set.
virtual bool IsVulkan() { return false; }
virtual bool IsPoly() { return false; }
virtual int GetShaderCount();
virtual bool CompileNextShader() { return true; }
void SetAABBTree(hwrenderer::LevelAABBTree * tree)
{
mShadowMap.SetAABBTree(tree);

View file

@ -28,51 +28,93 @@
#include "version.h"
#include <ShaderLang.h>
bool VkShaderManager::CompileNextShader()
{
const char *mainvp = "shaders/glsl/main.vp";
const char *mainfp = "shaders/glsl/main.fp";
int i = compileIndex;
if (compileState == 0)
{
// regular material shaders
VkShaderProgram prog;
prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, compilePass == GBUFFER_PASS);
mMaterialShaders[compilePass].push_back(std::move(prog));
compileIndex++;
if (defaultshaders[compileIndex].ShaderName == nullptr)
{
compileIndex = 0;
compileState++;
}
}
else if (compileState == 1)
{
// NAT material shaders
VkShaderProgram natprog;
natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, compilePass == GBUFFER_PASS);
mMaterialShadersNAT[compilePass].push_back(std::move(natprog));
compileIndex++;
if (compileIndex == SHADER_NoTexture)
{
compileIndex = 0;
compileState++;
if (usershaders.Size() == 0) compileState++;
}
}
else if (compileState == 2)
{
// user shaders
const FString& name = ExtractFileBase(usershaders[i].shader);
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
VkShaderProgram prog;
prog.vert = LoadVertShader(name, mainvp, defines);
prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, compilePass == GBUFFER_PASS);
mMaterialShaders[compilePass].push_back(std::move(prog));
compileIndex++;
if (compileIndex >= (int)usershaders.Size())
{
compileIndex = 0;
compileState++;
}
}
else if (compileState == 3)
{
// Effect shaders
VkShaderProgram prog;
prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines);
prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, compilePass == GBUFFER_PASS);
mEffectShaders[compilePass].push_back(std::move(prog));
compileIndex++;
if (compileIndex >= MAX_EFFECTS)
{
compileIndex = 0;
compilePass++;
if (compilePass == MAX_PASS_TYPES)
{
compileIndex = -1; // we're done.
return true;
}
compileState = 0;
}
}
return false;
}
VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device)
{
ShInitialize();
const char *mainvp = "shaders/glsl/main.vp";
const char *mainfp = "shaders/glsl/main.fp";
for (int j = 0; j < MAX_PASS_TYPES; j++)
{
bool gbufferpass = j;
for (int i = 0; defaultshaders[i].ShaderName != nullptr; i++)
{
VkShaderProgram prog;
prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass);
mMaterialShaders[j].push_back(std::move(prog));
if (i < SHADER_NoTexture)
{
VkShaderProgram natprog;
natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass);
mMaterialShadersNAT[j].push_back(std::move(natprog));
}
}
for (unsigned i = 0; i < usershaders.Size(); i++)
{
FString name = ExtractFileBase(usershaders[i].shader);
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
VkShaderProgram prog;
prog.vert = LoadVertShader(name, mainvp, defines);
prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass);
mMaterialShaders[j].push_back(std::move(prog));
}
for (int i = 0; i < MAX_EFFECTS; i++)
{
VkShaderProgram prog;
prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines);
prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, gbufferpass);
mEffectShaders[j].push_back(std::move(prog));
}
}
CompileNextShader();
}
VkShaderManager::~VkShaderManager()
@ -82,7 +124,7 @@ VkShaderManager::~VkShaderManager()
VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
{
if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
if (compileIndex == -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
{
return &mEffectShaders[passType][effect];
}
@ -91,8 +133,9 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
{
if (compileIndex != -1) return &mMaterialShaders[0][0];
// indices 0-2 match the warping modes, 3 no texture, the following are custom
if (!alphateston && eff <= 2)
if (!alphateston && eff < SHADER_NoTexture)
{
return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2. The rest won't get used anyway
}

View file

@ -65,6 +65,7 @@ public:
VkShaderProgram *GetEffect(int effect, EPassType passType);
VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType);
bool CompileNextShader();
private:
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines);
@ -79,4 +80,6 @@ private:
std::vector<VkShaderProgram> mMaterialShaders[MAX_PASS_TYPES];
std::vector<VkShaderProgram> mMaterialShadersNAT[MAX_PASS_TYPES];
std::vector<VkShaderProgram> mEffectShaders[MAX_PASS_TYPES];
uint8_t compilePass = 0, compileState = 0;
int compileIndex = 0;
};

View file

@ -277,16 +277,20 @@ void VulkanDevice::CreateInstance()
Extensions = GetExtensions();
EnabledExtensions = GetPlatformExtensions();
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
std::string debugLayer = "VK_LAYER_KHRONOS_validation";
bool wantDebugLayer = vk_debug;
bool debugLayerFound = false;
for (const VkLayerProperties &layer : AvailableLayers)
if (wantDebugLayer)
{
if (layer.layerName == debugLayer && wantDebugLayer)
for (const VkLayerProperties& layer : AvailableLayers)
{
EnabledValidationLayers.push_back(debugLayer.c_str());
EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
debugLayerFound = true;
if (layer.layerName == debugLayer)
{
EnabledValidationLayers.push_back(layer.layerName);
EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
debugLayerFound = true;
break;
}
}
}

View file

@ -207,6 +207,11 @@ void VulkanFrameBuffer::Update()
Super::Update();
}
bool VulkanFrameBuffer::CompileNextShader()
{
return mShaderManager->CompileNextShader();
}
void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly)
{
FrameTextureUpload.Buffers.clear();

View file

@ -77,7 +77,7 @@ public:
void Update() override;
void InitializeState() override;
bool CompileNextShader() override;
void PrecacheMaterial(FMaterial *mat, int translation) override;
void UpdatePalette() override;
const char* DeviceName() const override;

View file

@ -209,13 +209,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step,
iCopyColors<cIA, cBGRA, op>, \
iCopyColors<cCMYK, cBGRA, op>, \
iCopyColors<cYCbCr, cBGRA, op>, \
iCopyColors<cYCCK, cBGRA, op>, \
iCopyColors<cBGR, cBGRA, op>, \
iCopyColors<cBGRA, cBGRA, op>, \
iCopyColors<cI16, cBGRA, op>, \
iCopyColors<cRGB555, cBGRA, op>, \
iCopyColors<cPalEntry, cBGRA, op> \
}
static const CopyFunc copyfuncs[][11]={
static const CopyFunc copyfuncs[][12]={
COPY_FUNCS(bCopy),
COPY_FUNCS(bBlend),
COPY_FUNCS(bAdd),

View file

@ -65,6 +65,7 @@ enum ColorType
CF_IA,
CF_CMYK,
CF_YCbCr,
CF_YCCK,
CF_BGR,
CF_BGRA,
CF_I16,
@ -326,6 +327,15 @@ struct cYCbCr
static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; }
};
struct cYCCK
{
static __forceinline unsigned char R(const unsigned char* p) { auto myR = cYCbCr::R(p); return p[3] - ((myR * p[3]) >> 8); }
static __forceinline unsigned char G(const unsigned char* p) { auto myG = cYCbCr::G(p); return p[3] - ((myG * p[3]) >> 8); }
static __forceinline unsigned char B(const unsigned char* p) { auto myB = cYCbCr::B(p); return p[3] - ((myB * p[3]) >> 8); }
static __forceinline unsigned char A(const unsigned char* p, uint8_t x, uint8_t y, uint8_t z) { return 255; }
static __forceinline int Gray(const unsigned char* p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; }
};
struct cBGR
{
static __forceinline unsigned char R(const unsigned char * p) { return p[2]; }

View file

@ -282,6 +282,7 @@ TArray<uint8_t> FJPEGTexture::CreatePalettedPixels(int conversion)
jpeg_read_header(&cinfo, TRUE);
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
(cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) ||
(cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
{
@ -350,6 +351,24 @@ TArray<uint8_t> FJPEGTexture::CreatePalettedPixels(int conversion)
}
break;
case JCS_YCCK:
// Probably useless but since I had the formula available...
for (int x = Width; x > 0; --x)
{
double Y = in[0], Cb = in[1], Cr = in[2];
int K = in[3];
int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255);
int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255);
int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255);
r = r - ((r * K) >> 8);
g = g - ((g * K) >> 8);
b = b - ((b * K) >> 8);
*out = ImageHelpers::RGBToPalette(doalpha, r, g, b);
out += Height;
in += 4;
}
break;
default:
// The other colorspaces were considered above and discarded,
// but GCC will complain without a default for them here.
@ -402,6 +421,7 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion)
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
(cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) ||
(cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
{
@ -439,6 +459,11 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion)
4, cinfo.output_width * cinfo.output_components, 0, CF_CMYK);
break;
case JCS_YCCK:
bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, 0, CF_YCCK);
break;
case JCS_YCbCr:
bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, 0, CF_YCbCr);

View file

@ -238,6 +238,8 @@
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(_MSC_VER) && defined(_M_ARM)
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(_MSC_VER) && defined(_M_ARM64)
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
# define RAPIDJSON_ENDIAN
# else

View file

@ -1023,10 +1023,10 @@ CCMD(secret)
maphdr.Format("[%s]", mapname);
FString linebuild;
char readbuffer[1024];
char readbuffer[10240];
bool inlevel = false;
while (lump.Gets(readbuffer, 1024))
while (lump.Gets(readbuffer, 10240))
{
if (!inlevel)
{

View file

@ -3356,6 +3356,10 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
}
V_Init2();
while(!screen->CompileNextShader())
{
// here we can do some visual updates later
}
twod->fullscreenautoaspect = gameinfo.fullscreenautoaspect;
// Initialize the size of the 2D drawer so that an attempt to access it outside the draw code won't crash.
twod->Begin(screen->GetWidth(), screen->GetHeight());

View file

@ -162,7 +162,7 @@ bool EventManager::UnregisterHandler(DStaticEventHandler* handler)
bool EventManager::SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual)
{
if (gamestate != GS_LEVEL)
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
return false;
Net_WriteByte(DEM_NETEVENT);

View file

@ -144,12 +144,7 @@ void DrawFullscreenSubtitle(FFont* font, const char *text)
void DIntermissionScreen::Init(FIntermissionAction *desc, bool first)
{
if (desc->mMusic.IsEmpty())
{
// only start the default music if this is the first action in an intermission
if (first) S_ChangeMusic (gameinfo.finaleMusic, gameinfo.finaleOrder, desc->mMusicLooping);
}
else
if (!first && desc->mMusic.IsNotEmpty())
{
S_ChangeMusic (desc->mMusic, desc->mMusicOrder, desc->mMusicLooping);
}
@ -193,8 +188,27 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first)
}
mTicker = 0;
mSubtitle = desc->mSubtitle;
mFirst = first;
// If this is the first element of an intermission we must delay starting the music until Start() is called.
mMusic = desc->mMusic;
mMusicLooping = desc->mMusicLooping;
mMusicOrder = desc->mMusicOrder;
}
void DIntermissionScreen::Start()
{
if (mFirst)
{
if (mMusic.IsEmpty())
{
S_ChangeMusic(gameinfo.finaleMusic, gameinfo.finaleOrder, mMusicLooping);
}
else
{
S_ChangeMusic(mMusic, mMusicOrder, mMusicLooping);
}
}
}
int DIntermissionScreen::Responder (FInputEvent *ev)
{
@ -900,6 +914,11 @@ again:
return false;
}
void DIntermissionController::Start()
{
if (mScreen) mScreen->Start();
}
bool DIntermissionController::Responder (FInputEvent *ev)
{
if (mScreen != NULL)
@ -994,6 +1013,7 @@ DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool
if (!CurrentIntermission->NextPage())
{
CurrentIntermission->Destroy();
return nullptr;
}
GC::WriteBarrier(CurrentIntermission);
@ -1042,10 +1062,17 @@ DEFINE_ACTION_FUNCTION(DIntermissionController, Ticker)
ACTION_RETURN_BOOL(self->Ticker());
}
DEFINE_ACTION_FUNCTION(DIntermissionController, Start)
{
PARAM_SELF_PROLOGUE(DIntermissionController);
self->Start();
return 0;
}
DEFINE_ACTION_FUNCTION(DIntermissionController, Drawer)
{
PARAM_SELF_PROLOGUE(DIntermissionController);
self->Drawer ();
self->Drawer();
return 0;
}

View file

@ -166,7 +166,11 @@ protected:
int mDuration;
FTextureID mBackground;
FString mSubtitle;
FString mMusic;
int mMusicOrder;
bool mMusicLooping;
bool mFlatfill;
bool mFirst;
TArray<FIIntermissionPatch> mOverlays;
bool CheckOverlay(int i);
@ -176,6 +180,7 @@ public:
DIntermissionScreen() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual void Start();
virtual int Responder (FInputEvent *ev);
virtual int Ticker ();
virtual void Drawer ();
@ -304,6 +309,7 @@ public:
DIntermissionController(FIntermissionDescriptor *mDesc = NULL, bool mDeleteDesc = false, bool ending = false);
bool Responder (FInputEvent *ev);
bool Ticker ();
void Start();
void Drawer ();
void OnDestroy() override;
bool NextPage();

View file

@ -345,7 +345,7 @@ FStrifeDialogueNode *MapLoader::ReadRetailNode (const char *name, FileReader &lu
for (j = 0; j < 3; ++j)
{
auto inv = GetStrifeType(speech.ItemCheck[j]);
if (!inv->IsDescendantOf(NAME_Inventory)) inv = nullptr;
if (inv == NULL || !inv->IsDescendantOf(NAME_Inventory)) inv = nullptr;
node->ItemCheck[j].Item = inv;
node->ItemCheck[j].Amount = -1;
}
@ -516,7 +516,7 @@ void MapLoader::ParseReplies (const char *name, int pos, FStrifeDialogueReply **
for (k = 0; k < 3; ++k)
{
auto inv = GetStrifeType(rsp->Item[k]);
if (!inv->IsDescendantOf(NAME_Inventory)) inv = nullptr;
if (inv == NULL || !inv->IsDescendantOf(NAME_Inventory)) inv = nullptr;
reply->ItemCheck[k].Item = inv;
reply->ItemCheck[k].Amount = rsp->Count[k];
}

View file

@ -423,7 +423,8 @@ enum ActorFlag8
MF8_MAP07BOSS2 = 0x00800000, // MBF21 boss death.
MF8_AVOIDHAZARDS = 0x01000000, // MBF AI enhancement.
MF8_STAYONLIFT = 0x02000000, // MBF AI enhancement.
MF8_DONTFOLLOWPLAYERS = 0x04000000, // [inkoalwetrust] Friendly monster will not follow players.
MF8_DONTFOLLOWPLAYERS = 0x04000000, // [inkoalawetrust] Friendly monster will not follow players.
MF8_SEEFRIENDLYMONSTERS = 0X08000000, // [inkoalawetrust] Hostile monster can see friendly monsters.
};
// --- mobj.renderflags ---

View file

@ -663,6 +663,7 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d
// 2. Other side is the next sector to raise
// 3. Unless already moving, or different texture, then stop building
validcount++;
sec->validcount = validcount;
do
{
ok = 0;

View file

@ -1555,25 +1555,32 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam)
continue;
other = NULL;
if (link->flags & MF_FRIENDLY)
if (lookee->flags & MF_FRIENDLY)
{
if (!lookee->IsFriend(link))
if (link->flags & MF_FRIENDLY)
{
// This is somebody else's friend, so go after it
other = link;
}
else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY))
{
other = link->target;
if (!(other->flags & MF_SHOOTABLE) ||
other->health <= 0 ||
(other->flags2 & MF2_DORMANT))
if (!lookee->IsFriend(link))
{
other = NULL;;
// This is somebody else's friend, so go after it
other = link;
}
else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY))
{
other = link->target;
if (!(other->flags & MF_SHOOTABLE) ||
other->health <= 0 ||
(other->flags2 & MF2_DORMANT))
{
other = NULL;;
}
}
}
else
{
other = link;
}
}
else
else if (lookee->flags8 & MF8_SEEFRIENDLYMONSTERS && link->flags & MF_FRIENDLY)
{
other = link;
}
@ -1617,7 +1624,7 @@ int P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params)
{
AActor *other;
other = P_BlockmapSearch (actor, actor->friendlyseeblocks, LookForEnemiesInBlock, params);
other = P_BlockmapSearch(actor, actor->friendlyseeblocks, LookForEnemiesInBlock, params);
if (other != NULL)
{
@ -1726,6 +1733,12 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
} // [SP] if false, and in deathmatch, intentional fall-through
else if (actor->flags8 & MF8_SEEFRIENDLYMONSTERS)
{
bool result = P_LookForEnemies (actor, allaround, params);
if (result) return true;
}
if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) &&
actor->Level->isPrimaryLevel() &&

View file

@ -76,6 +76,7 @@ EXTERN_CVAR (Bool, show_obituaries)
CVAR (Float, sv_damagefactormobj, 1.0, CVAR_SERVERINFO|CVAR_CHEAT)
CVAR (Float, sv_damagefactorfriendly, 1.0, CVAR_SERVERINFO|CVAR_CHEAT)
CVAR (Float, sv_damagefactorplayer, 1.0, CVAR_SERVERINFO|CVAR_CHEAT)
CVAR (Float, sv_ammofactor, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) // used in the zscript ammo code
//
// GET STUFF

View file

@ -339,6 +339,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF8, AVOIDHAZARDS, AActor, flags8),
DEFINE_FLAG(MF8, STAYONLIFT, AActor, flags8),
DEFINE_FLAG(MF8, DONTFOLLOWPLAYERS, AActor, flags8),
DEFINE_FLAG(MF8, SEEFRIENDLYMONSTERS, AActor, flags8),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -12,6 +12,7 @@ class BossBrain : Actor
Health 250;
Mass 10000000;
PainChance 255;
Radius 16;
+SOLID +SHOOTABLE
+NOICEDEATH
+OLDRADIUSDMG

View file

@ -94,7 +94,7 @@ class Ammo : Inventory
if (!item.bIgnoreSkill)
{ // extra ammo in baby mode and nightmare mode
receiving = int(receiving * G_SkillPropertyFloat(SKILLP_AmmoFactor));
receiving = int(receiving * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
}
int oldamount = Amount;
@ -140,7 +140,7 @@ class Ammo : Inventory
// extra ammo in baby mode and nightmare mode
if (!bIgnoreSkill)
{
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
}
let type = GetParentAmmo();
@ -258,7 +258,7 @@ class BackpackItem : Inventory
// extra ammo in baby mode and nightmare mode
if (!bIgnoreSkill)
{
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
}
if (amount < 0) amount = 0;
if (ammoitem == NULL)
@ -323,7 +323,7 @@ class BackpackItem : Inventory
// extra ammo in baby mode and nightmare mode
if (!bIgnoreSkill)
{
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
}
ammoitem.Amount += amount;
if (ammoitem.Amount > ammoitem.MaxAmount && !sv_unlimited_pickup)

View file

@ -748,7 +748,7 @@ class Weapon : StateProvider
// extra ammoitem in baby mode and nightmare mode
if (!bIgnoreSkill)
{
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
}
ammoitem = Ammo(other.FindInventory (ammotype));
if (ammoitem == NULL)
@ -783,7 +783,7 @@ class Weapon : StateProvider
// extra ammo in baby mode and nightmare mode
if (!bIgnoreSkill)
{
amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor));
amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor));
}
ammo.Amount += amount;
if (ammo.Amount > ammo.MaxAmount && !sv_unlimited_pickup)

View file

@ -5,6 +5,7 @@ class IntermissionController native ui
// This is mostly a black box to the native intermission code.
// May be scriptified later, but right now we do not need it.
native void Start();
native bool Responder(InputEvent ev);
native bool Ticker();
native void Drawer();
@ -24,6 +25,7 @@ class IntermissionScreenJob : ScreenJob
return self;
}
override void Start() { controller.Start(); }
override bool OnEvent(InputEvent evt) { return controller.Responder(evt); }
override void OnTick() { if (!controller.Ticker()) jobstate = finished; }
override void Draw(double smoothratio) { controller.Drawer(); }

View file

@ -497,14 +497,13 @@ class ConversationMenu : Menu
double sx = (x - 160.0) * CleanXfac + (screen.GetWidth() * 0.5);
double sy = (y - 100.0) * CleanYfac + (screen.GetHeight() * 0.5);
ypositions.Push(sy);
screen.DrawText(displayFont, Font.CR_GREEN, sx / fontScale, sy / fontScale, mResponseLines[i], DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight);
if (i == mResponses[response])
{
String tbuf;
ypositions.Push(sy);
response++;
tbuf = String.Format("%d.", response);
x = 50 - displayFont.StringWidth(tbuf);