From f77979d904bb2fbebbadf424f8e0d830adeba8e7 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 13 Feb 2016 15:48:33 -0500 Subject: [PATCH] Increase rendering performance significantly --- moonlight.hpp | 10 +++++++--- viddec.cpp | 50 +++++++++++++++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/moonlight.hpp b/moonlight.hpp index af69b97..8773c28 100644 --- a/moonlight.hpp +++ b/moonlight.hpp @@ -17,6 +17,8 @@ #include "nacl_io/nacl_io.h" +#include + #include struct Shader { @@ -32,6 +34,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { explicit MoonlightInstance(PP_Instance instance) : pp::Instance(instance), pp::MouseLock(this), + m_IsPainting(false), m_CallbackFactory(this), m_MouseLocked(false) { // This function MUST be used otherwise sockets don't work (nacl_io_init() doesn't work!) @@ -70,11 +73,11 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { static Shader CreateProgram(const char* vertexShader, const char* fragmentShader); static void CreateShader(GLuint program, GLenum type, const char* source, int size); - static void PaintPicture(PP_VideoPicture picture); - void DispatchRendering(int32_t unused); + void PaintFinished(int32_t result); void DispatchGetPicture(uint32_t unused); void PictureReady(int32_t result, PP_VideoPicture picture); + void PaintPicture(void); static void VidDecSetup(int width, int height, int redrawRate, void* context, int drFlags); static void VidDecCleanup(void); @@ -90,7 +93,8 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { Shader m_Texture2DShader; Shader m_RectangleArbShader; Shader m_ExternalOesShader; - PP_VideoPicture m_LastPicture; + std::queue m_PendingPictureQueue; + bool m_IsPainting; double m_LastPadTimestamps[4]; const PPB_Gamepad* m_GamepadApi; diff --git a/viddec.cpp b/viddec.cpp index 24629b9..6cc06f0 100644 --- a/viddec.cpp +++ b/viddec.cpp @@ -108,7 +108,7 @@ void MoonlightInstance::DidChangeView(const pp::Rect& position, GL_STATIC_DRAW); assertNoGLError(); - g_Instance->m_Graphics3D.SwapBuffers(g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::DispatchRendering)); + g_Instance->m_Graphics3D.SwapBuffers(pp::BlockUntilComplete()); } void MoonlightInstance::VidDecSetup(int width, int height, int redrawRate, void* context, int drFlags) { @@ -128,12 +128,6 @@ void MoonlightInstance::VidDecSetup(int width, int height, int redrawRate, void* } void MoonlightInstance::DispatchGetPicture(uint32_t unused) { - /*glClearColor(0.5, 0.5, 0.5, 1); - glClear(GL_COLOR_BUFFER_BIT); - - m_Graphics3D.SwapBuffers( - m_CallbackFactory.NewCallback(&MoonlightInstance::DispatchGetPicture));*/ - // Queue the initial GetPicture callback on the main thread g_Instance->m_VideoDecoder->GetPicture( g_Instance->m_CallbackFactory.NewCallbackWithOutput(&MoonlightInstance::PictureReady)); @@ -217,7 +211,18 @@ Shader MoonlightInstance::CreateProgram(const char* vertexShader, const char* fr return shader; } -void MoonlightInstance::PaintPicture(PP_VideoPicture picture) { +void MoonlightInstance::PaintPicture(void) { + m_IsPainting = true; + + // Free and skip all frames except the latest one + PP_VideoPicture picture; + while (m_PendingPictureQueue.size() > 1) { + picture = m_PendingPictureQueue.front(); + m_PendingPictureQueue.pop(); + g_Instance->m_VideoDecoder->RecyclePicture(picture); + } + + picture = m_PendingPictureQueue.front(); if (picture.texture_target == GL_TEXTURE_2D) { if (!g_Instance->m_Texture2DShader.program) { g_Instance->m_Texture2DShader = CreateProgram(k_VertexShader, k_FragmentShader2D); @@ -249,12 +254,21 @@ void MoonlightInstance::PaintPicture(PP_VideoPicture picture) { glUseProgram(0); } - g_Instance->m_Graphics3D.SwapBuffers(g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::DispatchRendering)); + g_Instance->m_Graphics3D.SwapBuffers( + g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::PaintFinished)); } -void MoonlightInstance::DispatchRendering(int32_t unused) { - // Paint the image on screen - PaintPicture(m_LastPicture); +void MoonlightInstance::PaintFinished(int32_t result) { + m_IsPainting = false; + + // Recycle the picture now that it's been painted + g_Instance->m_VideoDecoder->RecyclePicture(m_PendingPictureQueue.front()); + m_PendingPictureQueue.pop(); + + // Keep painting if we still have frames + if (!m_PendingPictureQueue.empty()) { + PaintPicture(); + } } void MoonlightInstance::PictureReady(int32_t result, PP_VideoPicture picture) { @@ -262,16 +276,14 @@ void MoonlightInstance::PictureReady(int32_t result, PP_VideoPicture picture) { return; } - // Replace the last picture with this one and free the old one - PP_VideoPicture oldPic = m_LastPicture; - m_LastPicture = picture; - if (oldPic.texture_target) { - g_Instance->m_VideoDecoder->RecyclePicture(oldPic); - } + m_PendingPictureQueue.push(picture); - // Queue another callback g_Instance->m_VideoDecoder->GetPicture( g_Instance->m_CallbackFactory.NewCallbackWithOutput(&MoonlightInstance::PictureReady)); + + if (!m_IsPainting) { + PaintPicture(); + } } DECODER_RENDERER_CALLBACKS MoonlightInstance::s_DrCallbacks = {