Add debug overlay for SDL renderer

This commit is contained in:
Cameron Gutman 2019-02-12 21:55:15 -08:00
parent 4dac57cf8c
commit 46bd8ad83d
5 changed files with 113 additions and 11 deletions

BIN
app/ModeSeven.ttf Normal file

Binary file not shown.

View File

@ -91,7 +91,7 @@ unix:!macx {
} }
} }
win32 { win32 {
LIBS += -llibssl -llibcrypto -lSDL2 -lavcodec -lavutil -lopus -ld3dx9 LIBS += -llibssl -llibcrypto -lSDL2 -lSDL2_ttf -lavcodec -lavutil -lopus -ld3dx9
CONFIG += ffmpeg soundio CONFIG += ffmpeg soundio
} }
macx { macx {
@ -307,7 +307,7 @@ unix:!macx: {
appstream.files = deploy/linux/com.moonlight_stream.Moonlight.appdata.xml appstream.files = deploy/linux/com.moonlight_stream.Moonlight.appdata.xml
appstream.path = $$PREFIX/$$DATADIR/metainfo/ appstream.path = $$PREFIX/$$DATADIR/metainfo/
appdata.files = SDL_GameControllerDB/gamecontrollerdb.txt appdata.files = SDL_GameControllerDB/gamecontrollerdb.txt ModeSeven.ttf
appdata.path = "$$PREFIX/$$DATADIR/Moonlight Game Streaming Project/Moonlight/" appdata.path = "$$PREFIX/$$DATADIR/Moonlight Game Streaming Project/Moonlight/"
INSTALLS += target appdata desktop icons appstream INSTALLS += target appdata desktop icons appstream
@ -328,7 +328,7 @@ macx {
QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist
APP_BUNDLE_RESOURCES.files = moonlight.icns SDL_GameControllerDB/gamecontrollerdb.txt APP_BUNDLE_RESOURCES.files = moonlight.icns SDL_GameControllerDB/gamecontrollerdb.txt ModeSeven.ttf
APP_BUNDLE_RESOURCES.path = Contents/Resources APP_BUNDLE_RESOURCES.path = Contents/Resources
APP_BUNDLE_FRAMEWORKS.files = $$files(../libs/mac/Frameworks/*.framework, true) APP_BUNDLE_FRAMEWORKS.files = $$files(../libs/mac/Frameworks/*.framework, true)

View File

@ -1,16 +1,49 @@
#include "sdlvid.h" #include "sdlvid.h"
#include "streaming/session.h"
#include <Limelight.h> #include <Limelight.h>
SdlRenderer::SdlRenderer() SdlRenderer::SdlRenderer()
: m_Renderer(nullptr), : m_Renderer(nullptr),
m_Texture(nullptr) m_Texture(nullptr),
m_DebugOverlayFont(nullptr),
m_DebugOverlaySurface(nullptr),
m_DebugOverlayTexture(nullptr)
{ {
SDL_assert(TTF_WasInit() == 0);
if (TTF_Init() != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"TTF_Init() failed: %s",
TTF_GetError());
return;
}
m_DebugOverlayFont = TTF_OpenFont("ModeSeven.ttf", 20);
if (m_DebugOverlayFont == nullptr) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"TTF_OpenFont() failed: %s",
TTF_GetError());
}
} }
SdlRenderer::~SdlRenderer() SdlRenderer::~SdlRenderer()
{ {
if (m_DebugOverlayFont != nullptr) {
TTF_CloseFont(m_DebugOverlayFont);
}
TTF_Quit();
SDL_assert(TTF_WasInit() == 0);
if (m_DebugOverlayTexture != nullptr) {
SDL_DestroyTexture(m_DebugOverlayTexture);
}
if (m_DebugOverlaySurface != nullptr) {
SDL_FreeSurface(m_DebugOverlaySurface);
}
if (m_Texture != nullptr) { if (m_Texture != nullptr) {
SDL_DestroyTexture(m_Texture); SDL_DestroyTexture(m_Texture);
} }
@ -48,6 +81,35 @@ IFFmpegRenderer::FramePacingConstraint SdlRenderer::getFramePacingConstraint()
return PACING_ANY; return PACING_ANY;
} }
void SdlRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
{
if (type == Overlay::OverlayDebug) {
if (m_DebugOverlayFont == nullptr) {
// Can't proceed without a font
return;
}
SDL_Surface* oldSurface = (SDL_Surface*)SDL_AtomicGetPtr((void**)&m_DebugOverlaySurface);
// Free the old surface
if (oldSurface != nullptr && SDL_AtomicCASPtr((void**)&m_DebugOverlaySurface, oldSurface, nullptr)) {
SDL_FreeSurface(oldSurface);
}
if (Session::get()->getOverlayManager().isOverlayEnabled(type)) {
// The _Wrapped variant is required for line breaks to work
SDL_Surface* surface = TTF_RenderText_Blended_Wrapped(m_DebugOverlayFont,
Session::get()->getOverlayManager().getOverlayText(type),
Session::get()->getOverlayManager().getOverlayColor(type),
1000);
SDL_AtomicSetPtr((void**)&m_DebugOverlaySurface, surface);
}
}
else {
SDL_assert(false);
}
}
bool SdlRenderer::initialize(SDL_Window* window, bool SdlRenderer::initialize(SDL_Window* window,
int, int,
int width, int width,
@ -109,6 +171,35 @@ void SdlRenderer::renderFrameAtVsync(AVFrame* frame)
frame->linesize[2]); frame->linesize[2]);
SDL_RenderClear(m_Renderer); SDL_RenderClear(m_Renderer);
// Draw the video content itself
SDL_RenderCopy(m_Renderer, m_Texture, nullptr, nullptr); SDL_RenderCopy(m_Renderer, m_Texture, nullptr, nullptr);
// Draw the overlays
if (Session::get()->getOverlayManager().isOverlayEnabled(Overlay::OverlayDebug)) {
// If a new surface has been created for updated overlay data, convert it into a texture.
// NB: We have to do this conversion at render-time because we can only interact
// with the renderer on a single thread.
SDL_Surface* surface = (SDL_Surface*)SDL_AtomicGetPtr((void**)&m_DebugOverlaySurface);
if (surface != nullptr && SDL_AtomicCASPtr((void**)&m_DebugOverlaySurface, surface, nullptr)) {
if (m_DebugOverlayTexture != nullptr) {
SDL_DestroyTexture(m_DebugOverlayTexture);
}
m_DebugOverlayRect.x = 0;
m_DebugOverlayRect.y = 0;
m_DebugOverlayRect.w = surface->w;
m_DebugOverlayRect.h = surface->h;
m_DebugOverlayTexture = SDL_CreateTextureFromSurface(m_Renderer, surface);
SDL_FreeSurface(surface);
}
// If we have a debug overlay texture, render it too
if (m_DebugOverlayTexture != nullptr) {
SDL_RenderCopy(m_Renderer, m_DebugOverlayTexture, nullptr, &m_DebugOverlayRect);
}
}
SDL_RenderPresent(m_Renderer); SDL_RenderPresent(m_Renderer);
} }

View File

@ -2,24 +2,31 @@
#include "renderer.h" #include "renderer.h"
#include <SDL_ttf.h>
class SdlRenderer : public IFFmpegRenderer { class SdlRenderer : public IFFmpegRenderer {
public: public:
SdlRenderer(); SdlRenderer();
virtual ~SdlRenderer(); virtual ~SdlRenderer() override;
virtual bool initialize(SDL_Window* window, virtual bool initialize(SDL_Window* window,
int videoFormat, int videoFormat,
int width, int width,
int height, int height,
int maxFps, int maxFps,
bool enableVsync); bool enableVsync) override;
virtual bool prepareDecoderContext(AVCodecContext* context); virtual bool prepareDecoderContext(AVCodecContext* context) override;
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame) override;
virtual bool needsTestFrame(); virtual bool needsTestFrame() override;
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities() override;
virtual FramePacingConstraint getFramePacingConstraint(); virtual FramePacingConstraint getFramePacingConstraint() override;
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
private: private:
SDL_Renderer* m_Renderer; SDL_Renderer* m_Renderer;
SDL_Texture* m_Texture; SDL_Texture* m_Texture;
TTF_Font* m_DebugOverlayFont;
SDL_Surface* m_DebugOverlaySurface;
SDL_Texture* m_DebugOverlayTexture;
SDL_Rect m_DebugOverlayRect;
}; };

View File

@ -123,6 +123,10 @@ echo Copying GC mapping list
copy %SOURCE_ROOT%\app\SDL_GameControllerDB\gamecontrollerdb.txt %DEPLOY_FOLDER% copy %SOURCE_ROOT%\app\SDL_GameControllerDB\gamecontrollerdb.txt %DEPLOY_FOLDER%
if !ERRORLEVEL! NEQ 0 goto Error if !ERRORLEVEL! NEQ 0 goto Error
echo Copying SDL overlay font
copy %SOURCE_ROOT%\app\ModeSeven.ttf %DEPLOY_FOLDER%
if !ERRORLEVEL! NEQ 0 goto Error
echo Deploying Qt dependencies echo Deploying Qt dependencies
windeployqt.exe --dir %DEPLOY_FOLDER% --%BUILD_CONFIG% --qmldir %SOURCE_ROOT%\app\gui --no-opengl-sw --no-compiler-runtime %BUILD_FOLDER%\app\%BUILD_CONFIG%\Moonlight.exe windeployqt.exe --dir %DEPLOY_FOLDER% --%BUILD_CONFIG% --qmldir %SOURCE_ROOT%\app\gui --no-opengl-sw --no-compiler-runtime %BUILD_FOLDER%\app\%BUILD_CONFIG%\Moonlight.exe
if !ERRORLEVEL! NEQ 0 goto Error if !ERRORLEVEL! NEQ 0 goto Error