mirror of
https://github.com/ZDoom/Raze.git
synced 2025-03-24 09:42:13 +00:00
- backend sync from gzdoom, again
This commit is contained in:
parent
6dcb8c0f6e
commit
d2b209261d
8 changed files with 217 additions and 111 deletions
|
@ -322,11 +322,11 @@ class VpxPlayer : public MoviePlayer
|
|||
unsigned width, height;
|
||||
TArray<uint8_t> Pic;
|
||||
TArray<uint8_t> readBuf;
|
||||
vpx_codec_iface_t *iface;
|
||||
vpx_codec_ctx_t codec{};
|
||||
vpx_codec_iter_t iter = nullptr;
|
||||
|
||||
uint32_t convnumer;
|
||||
uint32_t convdenom;
|
||||
double convrate;
|
||||
|
||||
uint64_t nsecsperframe;
|
||||
uint64_t nextframetime;
|
||||
|
@ -362,10 +362,8 @@ public:
|
|||
|
||||
Pic.Resize(width * height * 4);
|
||||
|
||||
|
||||
// Todo: Support VP9 as well?
|
||||
vpx_codec_dec_cfg_t cfg = { 1, width, height };
|
||||
if (vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0))
|
||||
if (vpx_codec_dec_init(&codec, iface, &cfg, 0))
|
||||
{
|
||||
error.Format("Error initializing VPX codec.\n");
|
||||
failed = true;
|
||||
|
@ -388,7 +386,16 @@ public:
|
|||
uint16_t length = fr.ReadUInt16();
|
||||
if (length != 32) return false;
|
||||
fr.Read(&magic, 4);
|
||||
if (magic != MAKE_ID('V', 'P', '8', '0')) return false;
|
||||
|
||||
switch (magic)
|
||||
{
|
||||
case MAKE_ID('V', 'P', '8', '0'):
|
||||
iface = &vpx_codec_vp8_dx_algo; break;
|
||||
case MAKE_ID('V', 'P', '9', '0'):
|
||||
iface = &vpx_codec_vp9_dx_algo; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
width = fr.ReadUInt16();
|
||||
height = fr.ReadUInt16();
|
||||
|
@ -398,15 +405,20 @@ public:
|
|||
if (numframes == 0) return false;
|
||||
fr.Seek(4, FileReader::SeekCur);
|
||||
|
||||
if (fpsdenominator > 1000 || fpsnumerator == 0 || fpsdenominator == 0)
|
||||
if (fpsnumerator == 0 || fpsdenominator == 0)
|
||||
{
|
||||
// default to 30 fps if the header does not provide useful info.
|
||||
fpsdenominator = 30;
|
||||
fpsnumerator = 1;
|
||||
}
|
||||
|
||||
convnumer = 120 * fpsnumerator;
|
||||
convdenom = fpsdenominator * origframedelay;
|
||||
if (origframedelay < 1)
|
||||
convrate = 0.0;
|
||||
else
|
||||
{
|
||||
convrate = 120.0 * double(fpsnumerator);
|
||||
convrate /= double(fpsdenominator) * double(origframedelay);
|
||||
}
|
||||
|
||||
nsecsperframe = int64_t(fpsnumerator) * 1'000'000'000 / fpsdenominator;
|
||||
nextframetime = 0;
|
||||
|
@ -475,32 +487,6 @@ public:
|
|||
dest[2] = v;
|
||||
}
|
||||
|
||||
bool CreateNextFrame()
|
||||
{
|
||||
auto img = GetFrameData();
|
||||
if (!img) return false;
|
||||
uint8_t const* const yplane = img->planes[VPX_PLANE_Y];
|
||||
uint8_t const* const uplane = img->planes[VPX_PLANE_U];
|
||||
uint8_t const* const vplane = img->planes[VPX_PLANE_V];
|
||||
|
||||
const int ystride = img->stride[VPX_PLANE_Y];
|
||||
const int ustride = img->stride[VPX_PLANE_U];
|
||||
const int vstride = img->stride[VPX_PLANE_V];
|
||||
|
||||
for (unsigned int y = 0; y < height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < width; x++)
|
||||
{
|
||||
uint8_t u = uplane[ustride * (y >> 1) + (x >> 1)];
|
||||
uint8_t v = vplane[vstride * (y >> 1) + (x >> 1)];
|
||||
|
||||
SetPixel(&Pic[(x + y * width) << 2], yplane[ystride * y + x], u, v);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
@ -525,7 +511,7 @@ public:
|
|||
Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false));
|
||||
}
|
||||
}
|
||||
animtex.SetSize(AnimTexture::YUV, width, height);
|
||||
animtex.SetSize(AnimTexture::VPX, width, height);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -534,6 +520,12 @@ public:
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool FormatSupported(vpx_img_fmt_t fmt)
|
||||
{
|
||||
return fmt == VPX_IMG_FMT_I420 || fmt == VPX_IMG_FMT_I444 || fmt == VPX_IMG_FMT_I422 || fmt == VPX_IMG_FMT_I440;
|
||||
}
|
||||
|
||||
|
||||
bool Frame(uint64_t clock) override
|
||||
{
|
||||
if (!AudioTrack.GetAudioStream() && MusicStream && clock != 0)
|
||||
|
@ -562,22 +554,38 @@ public:
|
|||
bool stop = false;
|
||||
if (clock >= nextframetime)
|
||||
{
|
||||
|
||||
|
||||
nextframetime += nsecsperframe;
|
||||
|
||||
if (!CreateNextFrame())
|
||||
{
|
||||
Printf(PRINT_BOLD, "Failed reading next frame\n");
|
||||
stop = true;
|
||||
while(clock >= nextframetime)
|
||||
{ // frameskipping
|
||||
auto img = GetFrameData();
|
||||
framenum++;
|
||||
nextframetime += nsecsperframe;
|
||||
if (framenum >= numframes || !img) break;
|
||||
}
|
||||
else
|
||||
|
||||
if (framenum < numframes)
|
||||
{
|
||||
animtex.SetFrame(nullptr, Pic.Data());
|
||||
auto img = GetFrameData();
|
||||
|
||||
if (!img || !FormatSupported(img->fmt))
|
||||
{
|
||||
Printf(PRINT_BOLD, "Failed reading next frame\n");
|
||||
stop = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
animtex.SetFrame(nullptr, img);
|
||||
}
|
||||
|
||||
framenum++;
|
||||
}
|
||||
framenum++;
|
||||
if (framenum >= numframes) stop = true;
|
||||
|
||||
bool nostopsound = (flags & NOSOUNDCUTOFF);
|
||||
int soundframe = convdenom ? Scale(framenum, convnumer, convdenom) : framenum;
|
||||
int soundframe = (convrate > 0.0) ? int(convrate * framenum) : framenum;
|
||||
if (soundframe > lastsoundframe)
|
||||
{
|
||||
if (soundtrack == -1)
|
||||
|
@ -895,7 +903,7 @@ MoviePlayer* OpenMovie(const char* filename, TArray<int>& ans, const int* framet
|
|||
}
|
||||
return anm;
|
||||
}
|
||||
else if (!memcmp(id, "DKIF\0\0 \0VP80", 12))
|
||||
else if (!memcmp(id, "DKIF\0\0 \0VP80", 12) || !memcmp(id, "DKIF\0\0 \0VP90", 12))
|
||||
{
|
||||
auto anm = new VpxPlayer(fr, ans, frameticks ? frameticks[1] : 0, flags, error);
|
||||
if (!anm->isvalid())
|
||||
|
|
|
@ -599,14 +599,14 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, float in
|
|||
|
||||
if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0))
|
||||
{
|
||||
prev = inter1_prev < 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
|
||||
prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1);
|
||||
}
|
||||
|
||||
TRS next;
|
||||
|
||||
if(frame2 >= 0 && (frame2_prev >= 0 || inter2_prev < 0))
|
||||
{
|
||||
next = inter2_prev < 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2);
|
||||
next = inter2_prev <= 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2);
|
||||
}
|
||||
|
||||
TRS bone;
|
||||
|
|
|
@ -214,10 +214,6 @@ class TObjPtr
|
|||
mutable DObject *o;
|
||||
};
|
||||
public:
|
||||
// before doing a backend sync - this needs to be addressed: https://github.com/ZDoom/Raze/actions/runs/8727418834/job/23944876872
|
||||
//TObjPtr() = default;
|
||||
|
||||
//TObjPtr(T t) : pp(t) {}
|
||||
|
||||
constexpr TObjPtr<T>& operator=(T q) noexcept
|
||||
{
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "bitmap.h"
|
||||
#include "texturemanager.h"
|
||||
|
||||
#include "vpx/vpx_image.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -46,39 +48,152 @@ void AnimTexture::SetFrameSize(int format, int width, int height)
|
|||
{
|
||||
pixelformat = format;
|
||||
FTexture::SetSize(width, height);
|
||||
Image.Resize(width * height * (format == Paletted ? 1 : 3));
|
||||
Image.Resize(width * height * 4);
|
||||
memset(Image.Data(), 0, Image.Size());
|
||||
}
|
||||
|
||||
void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
|
||||
//TODO optimize
|
||||
static inline void YUVtoRGB(uint8_t yi, uint8_t ui, uint8_t vi, uint8_t * rgb)
|
||||
{
|
||||
float Y = yi * (1 / 255.f);
|
||||
float U = ui * (1 / 255.f) - 0.5f;
|
||||
float V = vi * (1 / 255.f) - 0.5f;
|
||||
Y = 1.1643f * (Y - 0.0625f);
|
||||
float r = Y + 1.5958f * V;
|
||||
float g = Y - 0.39173f * U - 0.81290f * V;
|
||||
float b = Y + 2.017f * U;
|
||||
(rgb)[2] = (uint8_t)(clamp(r, 0.f, 1.f) * 255);
|
||||
(rgb)[1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255);
|
||||
(rgb)[0] = (uint8_t)(clamp(b, 0.f, 1.f) * 255);
|
||||
(rgb)[3] = 255;
|
||||
}
|
||||
|
||||
void AnimTexture::SetFrame(const uint8_t* Palette, const void* data_)
|
||||
{
|
||||
if (palette) memcpy(Palette, palette, 768);
|
||||
if (data_)
|
||||
{
|
||||
auto dpix = Image.Data();
|
||||
|
||||
if (pixelformat == YUV)
|
||||
{
|
||||
auto spix = (const uint8_t*)data_;
|
||||
auto dpix = Image.Data();
|
||||
const uint8_t * spix = reinterpret_cast<const uint8_t *>(data_);
|
||||
|
||||
for (int i = 0; i < Width * Height; i++)
|
||||
{
|
||||
int p = i * 4;
|
||||
int q = i * 3;
|
||||
float y = spix[p] * (1 / 255.f);
|
||||
float u = spix[p + 1] * (1 / 255.f) - 0.5f;
|
||||
float v = spix[p + 2] * (1 / 255.f) - 0.5f;
|
||||
{
|
||||
YUVtoRGB(spix[0], spix[1], spix[2], dpix);
|
||||
|
||||
y = 1.1643f * (y - 0.0625f);
|
||||
|
||||
float r = y + 1.5958f * v;
|
||||
float g = y - 0.39173f * u - 0.81290f * v;
|
||||
float b = y + 2.017f * u;
|
||||
|
||||
dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255);
|
||||
dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255);
|
||||
dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255);
|
||||
spix += 4;
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
else if(pixelformat == VPX)
|
||||
{
|
||||
const vpx_image_t *img = reinterpret_cast<const vpx_image_t *>(data_);
|
||||
|
||||
uint8_t const* const yplane = img->planes[VPX_PLANE_Y];
|
||||
uint8_t const* const uplane = img->planes[VPX_PLANE_U];
|
||||
uint8_t const* const vplane = img->planes[VPX_PLANE_V];
|
||||
|
||||
const int ystride = img->stride[VPX_PLANE_Y];
|
||||
const int ustride = img->stride[VPX_PLANE_U];
|
||||
const int vstride = img->stride[VPX_PLANE_V];
|
||||
|
||||
if(img->fmt == VPX_IMG_FMT_I420)
|
||||
{
|
||||
for (unsigned int y = 0; y < Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < Width; x++)
|
||||
{
|
||||
YUVtoRGB(
|
||||
yplane[ystride * y + x],
|
||||
uplane[ustride * (y >> 1) + (x >> 1)],
|
||||
vplane[vstride * (y >> 1) + (x >> 1)],
|
||||
dpix
|
||||
);
|
||||
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(img->fmt == VPX_IMG_FMT_I444)
|
||||
{
|
||||
for (unsigned int y = 0; y < Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < Width; x++)
|
||||
{
|
||||
YUVtoRGB(
|
||||
yplane[ystride * y + x],
|
||||
uplane[ustride * y + x],
|
||||
vplane[vstride * y + x],
|
||||
dpix
|
||||
);
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(img->fmt == VPX_IMG_FMT_I422)
|
||||
{ // 422 and 440 untested
|
||||
for (unsigned int y = 0; y < Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < Width; x++)
|
||||
{
|
||||
YUVtoRGB(
|
||||
yplane[ystride * y + x],
|
||||
uplane[ustride * y + (x >> 1)],
|
||||
vplane[vstride * y + (x >> 1)],
|
||||
dpix
|
||||
);
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(img->fmt == VPX_IMG_FMT_I440)
|
||||
{
|
||||
for (unsigned int y = 0; y < Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < Width; x++)
|
||||
{
|
||||
YUVtoRGB(
|
||||
yplane[ystride * y + x],
|
||||
uplane[ustride * (y >> 1) + x],
|
||||
vplane[vstride * (y >> 1) + x],
|
||||
dpix
|
||||
);
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(pixelformat == RGB)
|
||||
{
|
||||
const uint8_t *img = reinterpret_cast<const uint8_t *>(data_);
|
||||
|
||||
for (int i = 0; i < Width * Height; i++)
|
||||
{
|
||||
dpix[0] = img[2];
|
||||
dpix[1] = img[1];
|
||||
dpix[2] = img[0];
|
||||
dpix[3] = 255;
|
||||
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
else if (pixelformat == Paletted)
|
||||
{
|
||||
assert(Palette);
|
||||
const uint8_t *img = reinterpret_cast<const uint8_t *>(data_);
|
||||
|
||||
for (int i = 0; i < Width * Height; i++)
|
||||
{
|
||||
int index = img[i];
|
||||
dpix[0] = Palette[index * 3 + 2];
|
||||
dpix[1] = Palette[index * 3 + 1];
|
||||
dpix[2] = Palette[index * 3];
|
||||
dpix[3] = 255;
|
||||
|
||||
dpix += 4;
|
||||
}
|
||||
}
|
||||
else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,37 +205,7 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_)
|
|||
|
||||
FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
|
||||
{
|
||||
FBitmap bmp;
|
||||
|
||||
bmp.Create(Width, Height);
|
||||
|
||||
auto spix = Image.Data();
|
||||
auto dpix = bmp.GetPixels();
|
||||
if (pixelformat == Paletted)
|
||||
{
|
||||
for (int i = 0; i < Width * Height; i++)
|
||||
{
|
||||
int p = i * 4;
|
||||
int index = spix[i];
|
||||
dpix[p + 0] = Palette[index * 3 + 2];
|
||||
dpix[p + 1] = Palette[index * 3 + 1];
|
||||
dpix[p + 2] = Palette[index * 3];
|
||||
dpix[p + 3] = 255;
|
||||
}
|
||||
}
|
||||
else if (pixelformat == RGB || pixelformat == YUV)
|
||||
{
|
||||
for (int i = 0; i < Width * Height; i++)
|
||||
{
|
||||
int p = i * 4;
|
||||
int q = i * 3;
|
||||
dpix[p + 0] = spix[q + 2];
|
||||
dpix[p + 1] = spix[q + 1];
|
||||
dpix[p + 2] = spix[q];
|
||||
dpix[p + 3] = 255;
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
return FBitmap(Image.Data(), Width * 4, Width, Height);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
class AnimTexture : public FTexture
|
||||
{
|
||||
uint8_t Palette[768];
|
||||
TArray<uint8_t> Image;
|
||||
int pixelformat;
|
||||
public:
|
||||
|
@ -13,7 +12,8 @@ public:
|
|||
{
|
||||
Paletted = 0,
|
||||
RGB = 1,
|
||||
YUV = 2
|
||||
YUV = 2,
|
||||
VPX = 3
|
||||
};
|
||||
AnimTexture() = default;
|
||||
void SetFrameSize(int format, int width, int height);
|
||||
|
|
|
@ -253,6 +253,8 @@ public:
|
|||
CopyPixelDataRGB(originx, originy, src.GetPixels(), src.GetWidth(), src.GetHeight(), 4, src.GetWidth()*4, 0, CF_BGRA, inf);
|
||||
}
|
||||
|
||||
|
||||
friend class FTexture;
|
||||
};
|
||||
|
||||
bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy,
|
||||
|
|
|
@ -354,17 +354,29 @@ FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags)
|
|||
|
||||
if (!checkonly)
|
||||
{
|
||||
buffer = new unsigned char[W * (H + 1) * 4];
|
||||
memset(buffer, 0, W * (H + 1) * 4);
|
||||
|
||||
auto remap = translation <= 0 || IsLuminosityTranslation(translation) ? nullptr : GPalette.TranslationToTable(translation);
|
||||
if (remap && remap->Inactive) remap = nullptr;
|
||||
if (remap) translation = remap->Index;
|
||||
FBitmap bmp(buffer, W * 4, W, H);
|
||||
|
||||
int trans;
|
||||
auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans);
|
||||
bmp.Blit(exx, exx, Pixels);
|
||||
|
||||
if(!exx && Pixels.ClipRect.x == 0 && Pixels.ClipRect.y == 0 && Pixels.ClipRect.width == Pixels.Width && Pixels.ClipRect.height == Pixels.Height && (Pixels.FreeBuffer || !IsLuminosityTranslation(translation)))
|
||||
{
|
||||
buffer = Pixels.data;
|
||||
result.mFreeBuffer = Pixels.FreeBuffer;
|
||||
Pixels.FreeBuffer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = new unsigned char[W * (H + 1) * 4];
|
||||
memset(buffer, 0, W * (H + 1) * 4);
|
||||
|
||||
FBitmap bmp(buffer, W * 4, W, H);
|
||||
|
||||
bmp.Blit(exx, exx, Pixels);
|
||||
}
|
||||
|
||||
if (IsLuminosityTranslation(translation))
|
||||
{
|
||||
V_ApplyLuminosityTranslation(LuminosityTranslationDesc::fromInt(translation), buffer, W * H);
|
||||
|
|
|
@ -169,6 +169,7 @@ union FContentIdBuilder
|
|||
struct FTextureBuffer
|
||||
{
|
||||
uint8_t *mBuffer = nullptr;
|
||||
bool mFreeBuffer = true;
|
||||
int mWidth = 0;
|
||||
int mHeight = 0;
|
||||
uint64_t mContentId = 0; // unique content identifier. (Two images created from the same image source with the same settings will return the same value.)
|
||||
|
@ -177,7 +178,7 @@ struct FTextureBuffer
|
|||
|
||||
~FTextureBuffer()
|
||||
{
|
||||
if (mBuffer) delete[] mBuffer;
|
||||
if (mBuffer && mFreeBuffer) delete[] mBuffer;
|
||||
}
|
||||
|
||||
FTextureBuffer(const FTextureBuffer &other) = delete;
|
||||
|
@ -187,6 +188,7 @@ struct FTextureBuffer
|
|||
mWidth = other.mWidth;
|
||||
mHeight = other.mHeight;
|
||||
mContentId = other.mContentId;
|
||||
mFreeBuffer = other.mFreeBuffer;
|
||||
other.mBuffer = nullptr;
|
||||
}
|
||||
|
||||
|
@ -196,6 +198,7 @@ struct FTextureBuffer
|
|||
mWidth = other.mWidth;
|
||||
mHeight = other.mHeight;
|
||||
mContentId = other.mContentId;
|
||||
mFreeBuffer = other.mFreeBuffer;
|
||||
other.mBuffer = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue