From 8cd9775513e5f8478649bb7672c0ed4bb8711bdb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 18 Jan 2020 15:18:04 +0100 Subject: [PATCH] - 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. --- source/build/src/animvpx.cpp | 125 ++++++++++++------- source/duke3d/src/anim.cpp | 14 +-- source/glbackend/glbackend.cpp | 25 ---- source/glbackend/glbackend.h | 3 - source/glbackend/hw_draw2d.cpp | 3 +- source/rr/src/anim.cpp | 11 +- wadsrc/static/engine/shaders/glsl/animvpx.fp | 29 ----- wadsrc/static/engine/shaders/glsl/animvpx.vp | 13 -- 8 files changed, 90 insertions(+), 133 deletions(-) delete mode 100644 wadsrc/static/engine/shaders/glsl/animvpx.fp delete mode 100644 wadsrc/static/engine/shaders/glsl/animvpx.vp diff --git a/source/build/src/animvpx.cpp b/source/build/src/animvpx.cpp index bce748dde..34ef50004 100644 --- a/source/build/src/animvpx.cpp +++ b/source/build/src/animvpx.cpp @@ -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 #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; diff --git a/source/duke3d/src/anim.cpp b/source/duke3d/src/anim.cpp index 660fc3ca2..7fa7cee52 100644 --- a/source/duke3d/src/anim.cpp +++ b/source/duke3d/src/anim.cpp @@ -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 { diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 728a2e1c9..91acf88f1 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -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 Vert = fr1.Read(); - fr1 = GetResource("engine/shaders/glsl/animvpx.fp"); - TArray 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); diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index 1b668e7cd..9d869ba0c 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -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); diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp index 3ee8b424c..9f2390ab4 100644 --- a/source/glbackend/hw_draw2d.cpp +++ b/source/glbackend/hw_draw2d.cpp @@ -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 diff --git a/source/rr/src/anim.cpp b/source/rr/src/anim.cpp index 0c08ae27a..b01da71be 100644 --- a/source/rr/src/anim.cpp +++ b/source/rr/src/anim.cpp @@ -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(); diff --git a/wadsrc/static/engine/shaders/glsl/animvpx.fp b/wadsrc/static/engine/shaders/glsl/animvpx.fp deleted file mode 100644 index 5bc67fb8b..000000000 --- a/wadsrc/static/engine/shaders/glsl/animvpx.fp +++ /dev/null @@ -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); -}; diff --git a/wadsrc/static/engine/shaders/glsl/animvpx.vp b/wadsrc/static/engine/shaders/glsl/animvpx.vp deleted file mode 100644 index 19db847f1..000000000 --- a/wadsrc/static/engine/shaders/glsl/animvpx.vp +++ /dev/null @@ -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; -} -