- fixed VP8 video player.

Also do the color space conversion on the CPU to avoid the shader hassle, performance wise it is utterly irrelevant here.
This commit is contained in:
Christoph Oelckers 2020-01-18 15:18:04 +01:00
parent 2e06ccfec6
commit 8cd9775513
8 changed files with 90 additions and 133 deletions

View file

@ -10,6 +10,9 @@
#include "matrix.h"
#include "../../glbackend/glbackend.h"
#include "textures.h"
#include "bitmap.h"
#include "v_draw.h"
#undef UNUSED
#define VPX_CODEC_DISABLE_COMPAT 1
@ -17,6 +20,74 @@
#include <vpx/vp8dx.h>
#include "animvpx.h"
class VPXTexture : public FTexture
{
public:
VPXTexture();
void SetFrame(const void* data, int width, int height);
virtual FBitmap GetBgraBitmap(const PalEntry* remap, int* trans) override;
protected:
const void* data;
public:
};
//==========================================================================
//
//
//
//==========================================================================
VPXTexture::VPXTexture() {}
void VPXTexture::SetFrame(const void *data_, int width, int height)
{
Size.x = width;
Size.y = height;
data = data_;
DeleteHardwareTextures();
}
//===========================================================================
//
// FPNGTexture::CopyPixels
//
//===========================================================================
FBitmap VPXTexture::GetBgraBitmap(const PalEntry* remap, int* trans)
{
FBitmap bmp;
bmp.Create(Size.x, Size.y);
auto spix = (uint8_t*)data;
auto dpix = bmp.GetPixels();
for (int i = 0; i < Size.x * Size.y; i++)
{
int p = i * 4;
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;
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[p + 0] = (uint8_t)(clamp(b, 0, 1.f) * 255);
dpix[p + 1] = (uint8_t)(clamp(g, 0, 1.f) * 255);
dpix[p + 2] = (uint8_t)(clamp(r, 0, 1.f) * 255);
dpix[p + 3] = 255;
}
return bmp;
}
const char *animvpx_read_ivf_header_errmsg[] = {
"All OK",
"couldn't read 32-byte IVF header",
@ -339,28 +410,13 @@ read_ivf_frame:
/////////////// DRAWING! ///////////////
static FHardwareTexture* texture;
static int sampler;
static int32_t texuploaded;
static VPXTexture* vpxtex;
void animvpx_setup_glstate(int32_t animvpx_flags)
{
static char logbuf[512];
GLInterface.SetVPXShader();
////////// GL STATE //////////
//Force fullscreen (glox1=-1 forces it to restore afterwards)
GLInterface.SetViewport(0,0,xdim,ydim); glox1 = -1;
GLInterface.EnableAlphaTest(false);
GLInterface.EnableDepthTest(false);
GLInterface.EnableBlend(false);
GLInterface.SetCull(Cull_None);
texture = GLInterface.NewTexture();
vpxtex = new VPXTexture;
if ((animvpx_flags & CUTSCENE_TEXTUREFILTER && hw_texfilter == TEXFILTER_ON) || animvpx_flags & CUTSCENE_FORCEFILTER ||
(!(animvpx_flags & CUTSCENE_TEXTUREFILTER) && !(animvpx_flags & CUTSCENE_FORCENOFILTER))) // if no flags, then use filter for IVFs
@ -372,18 +428,14 @@ void animvpx_setup_glstate(int32_t animvpx_flags)
sampler = SamplerNoFilterClampXY;
}
texuploaded = 0;
////////////////////
GLInterface.ClearScreen(0, true);
}
void animvpx_restore_glstate(void)
{
GLInterface.SetPolymostShader();
delete texture;
texture = nullptr;
texuploaded = 0;
delete vpxtex;
vpxtex = nullptr;
}
int32_t animvpx_render_frame(animvpx_codec_ctx *codec, double animvpx_aspect)
@ -396,13 +448,7 @@ int32_t animvpx_render_frame(animvpx_codec_ctx *codec, double animvpx_aspect)
if (codec->pic == NULL)
return 2; // shouldn't happen
if (!texuploaded)
{
texture->CreateTexture(codec->width, codec->height, FHardwareTexture::TrueColor, false);
texuploaded = 1;
}
texture->LoadTexture(codec->pic);
GLInterface.BindTexture(0, texture, sampler);
vpxtex->SetFrame(codec->pic, codec->width, codec->height);
float vid_wbyh = ((float)codec->width)/codec->height;
if (animvpx_aspect > 0)
@ -422,22 +468,9 @@ int32_t animvpx_render_frame(animvpx_codec_ctx *codec, double animvpx_aspect)
}
#endif
auto data = GLInterface.AllocVertices(4);
auto vt = data.second;
vt[0].SetTexCoord(0.0,1.0);
vt[0].SetVertex(-x, -y, 0.0);
vt[1].SetTexCoord(0.0,0.0);
vt[1].SetVertex(-x, y, 0.0);
vt[2].SetTexCoord(1.0,0.0);
vt[2].SetVertex(x, y, 0.0);
vt[3].SetTexCoord(1.0,1.0);
vt[3].SetVertex(x, -y, 0.0);
GLInterface.DrawIm(DT_TRIANGLE_FAN, data.first, 4);
x *= screen->GetWidth() / 2;
y *= screen->GetHeight() / 2;
DrawTexture(twod, vpxtex, screen->GetWidth() / 2 - int(x), screen->GetHeight()/2 - int(y), DTA_DestWidth, 2*int(x), DTA_DestHeight, 2*int(y), DTA_Masked, false, DTA_KeepRatio, true, TAG_DONE);
t = timerGetTicks()-t;
codec->sumtimes[2] += t;

View file

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "cmdlib.h"
#include "compat.h"
#include "build.h"
#include "v_2ddrawer.h"
#include "../glbackend/glbackend.h"
@ -303,6 +304,10 @@ int32_t Anim_Play(const char *fn)
// OSD_Printf("msecs per frame: %d\n", msecsperframe);
GLInterface.EnableNonTransparent255(true);
// Dummy rotatesprite call. Without this the movie won't render. Apparently some state isn't initialized properly and gets reset by this.
// Needs to be investigated. Leave this in as a workaround for now...
rotatesprite_fs(int(160 * 65536), int(100 * 65536) + ((28) << 16), 65536L, 0, 2499, 0, 0, 10);
do
{
nextframetime += msecsperframe;
@ -325,7 +330,7 @@ int32_t Anim_Play(const char *fn)
VM_OnEventWithReturn(EVENT_PRECUTSCENE, g_player[screenpeek].ps->i, screenpeek, framenum);
videoClearScreen(0);
twod->ClearScreen();
ototalclock = totalclock + 1; // pause game like ANMs
@ -376,12 +381,7 @@ int32_t Anim_Play(const char *fn)
}
}
// this and showframe() instead of nextpage() are so that
// nobody tramples on our carefully set up GL state!
palfadedelta = 0;
videoShowFrame(0);
// inputState.ClearAllInput();
videoNextPage();
do
{

View file

@ -92,7 +92,6 @@ void GLInstance::Init(int ydim)
new(&renderState) PolymostRenderState; // reset to defaults.
LoadSurfaceShader();
LoadVPXShader();
LoadPolymostShader();
#if 0
IMGUI_CHECKVERSION();
@ -128,19 +127,6 @@ void GLInstance::LoadPolymostShader()
SetPolymostShader();
}
void GLInstance::LoadVPXShader()
{
auto fr1 = GetResource("engine/shaders/glsl/animvpx.vp");
TArray<uint8_t> Vert = fr1.Read();
fr1 = GetResource("engine/shaders/glsl/animvpx.fp");
TArray<uint8_t> Frag = fr1.Read();
// Zero-terminate both strings.
Vert.Push(0);
Frag.Push(0);
vpxShader = new FShader();
vpxShader->Load("VPXShader", (const char*)Vert.Data(), (const char*)Frag.Data());
}
void GLInstance::LoadSurfaceShader()
{
auto fr1 = GetResource("engine/shaders/glsl/glsurface.vp");
@ -194,8 +180,6 @@ void GLInstance::Deinit()
polymostShader = nullptr;
if (surfaceShader) delete surfaceShader;
surfaceShader = nullptr;
if (vpxShader) delete vpxShader;
vpxShader = nullptr;
activeShader = nullptr;
palmanager.DeleteAllTextures();
lastPalswapIndex = -1;
@ -349,15 +333,6 @@ void GLInstance::SetSurfaceShader()
}
}
void GLInstance::SetVPXShader()
{
if (activeShader != vpxShader)
{
vpxShader->Bind();
activeShader = vpxShader;
}
}
void GLInstance::SetPalette(int index)
{
palmanager.BindPalette(index);

View file

@ -202,7 +202,6 @@ class GLInstance
FShader* activeShader;
PolymostShader* polymostShader;
SurfaceShader* surfaceShader;
FShader* vpxShader;
public:
@ -213,7 +212,6 @@ public:
void InitGLState(int fogmode, int multisample);
void LoadPolymostShader();
void LoadSurfaceShader();
void LoadVPXShader();
void Draw2D(F2DDrawer* drawer);
void DrawImGui(ImDrawData*);
void ResetFrame();
@ -262,7 +260,6 @@ public:
void SetPolymostShader();
void SetSurfaceShader();
void SetVPXShader();
void SetPalette(int palette);
void ReadPixels(int w, int h, uint8_t* buffer);

View file

@ -172,15 +172,14 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
SetShade(cmd.mRemapIndex >> 16, numshades);
SetFadeDisable(false);
SetTexture(0, tex, cmd.mRemapIndex & 0xffff, 4/*DAMETH_CLAMPED*/, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
EnableBlend(!(cmd.mRenderStyle.Flags & STYLEF_Alpha1));
}
else
{
SetFadeDisable(true);
SetShade(0, numshades);
SetNamedTexture(cmd.mTexture, cmd.mRemapIndex, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
EnableBlend(true);
}
EnableBlend(!(cmd.mRenderStyle.Flags & STYLEF_Alpha1));
UseColorOnly(false);
}
else

View file

@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "animlib.h"
#include "compat.h"
#include "cmdlib.h"
#include "v_2ddrawer.h"
#include "../glbackend/glbackend.h"
@ -359,7 +360,7 @@ int32_t Anim_Play(const char *fn)
if (!pic)
break; // no more pics!
videoClearScreen(0);
twod->ClearScreen();
ototalclock = totalclock + 1; // pause game like ANMs
@ -408,13 +409,7 @@ int32_t Anim_Play(const char *fn)
}
}
// this and showframe() instead of nextpage() are so that
// nobody tramples on our carefully set up GL state!
palfadedelta = 0;
videoShowFrame(0);
// inputState.ClearAllInput();
videoNextPage();
do
{
G_HandleAsync();

View file

@ -1,29 +0,0 @@
// YUV->RGB conversion fragment shader adapted from
// http://www.fourcc.org/fccyvrgb.php: Want some sample code?
// direct link: http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c
#version 330
uniform sampler2D tex;
in vec2 v_texCoord;
out vec4 FragColor;
void main(void) {
float r,g,b,y,u,v;
vec3 yuv;
yuv = texture2D(tex, v_texCoord.st).rgb;
y = yuv.r;
u = yuv.g;
v = yuv.b;
y = 1.1643*(y-0.0625);
u = u-0.5;
v = v-0.5;
r = y + 1.5958*v;
g = y - 0.39173*u - 0.81290*v;
b = y + 2.017*u;
FragColor = vec4(r,g,b,1.0);
};

View file

@ -1,13 +0,0 @@
#version 330
in vec4 i_vertPos;
in vec4 i_texCoord;
out vec2 v_texCoord;
void main()
{
gl_Position = i_vertPos;
v_texCoord = i_texCoord.st;
}