From 1142d2ee7b6b0717b6debd545e4d3b7208e83973 Mon Sep 17 00:00:00 2001 From: staphen Date: Tue, 21 Sep 2021 14:41:56 -0400 Subject: [PATCH] Hardware rendering for the virtual gamepad --- Source/DiabloUI/art.h | 12 ++++ Source/controls/touch/renderers.cpp | 108 ++++++++++++++++++---------- Source/controls/touch/renderers.h | 56 +++++++-------- Source/diablo.cpp | 4 +- Source/dx.cpp | 7 ++ Source/scrollrt.cpp | 6 -- 6 files changed, 118 insertions(+), 75 deletions(-) diff --git a/Source/DiabloUI/art.h b/Source/DiabloUI/art.h index c339001ad..b513965a0 100644 --- a/Source/DiabloUI/art.h +++ b/Source/DiabloUI/art.h @@ -13,6 +13,10 @@ struct Art { int frame_height; unsigned int palette_version; +#ifndef USE_SDL1 + SDLTextureUniquePtr texture; +#endif + Art() { surface = nullptr; @@ -20,6 +24,10 @@ struct Art { logical_width = 0; frame_height = 0; // logical frame height (before scaling) palette_version = 0; + +#ifndef USE_SDL1 + texture = nullptr; +#endif } int w() const @@ -35,6 +43,10 @@ struct Art { void Unload() { surface = nullptr; + +#ifndef USE_SDL1 + texture = nullptr; +#endif } }; diff --git a/Source/controls/touch/renderers.cpp b/Source/controls/touch/renderers.cpp index b6fae5a66..96834f7d5 100644 --- a/Source/controls/touch/renderers.cpp +++ b/Source/controls/touch/renderers.cpp @@ -5,6 +5,7 @@ #include "doom.h" #include "engine.h" #include "gendung.h" +#include "init.h" #include "inv.h" #include "minitext.h" #include "stores.h" @@ -53,48 +54,85 @@ VirtualGamepadButtonType GetBlankButtonType(bool isPressed) } // namespace -void DrawVirtualGamepad(const Surface &out) +void RenderVirtualGamepad(SDL_Renderer *renderer) { - Renderer.Render(out); + RenderFunction renderFunction = [&](Art &art, SDL_Rect *src, SDL_Rect *dst) { + if (art.texture == nullptr) + return; + + if (SDL_RenderCopy(renderer, art.texture.get(), src, dst) <= -1) + ErrSdl(); + }; + + Renderer.Render(renderFunction); } -void VirtualGamepadRenderer::LoadArt() +void RenderVirtualGamepad(SDL_Surface *surface) { - directionPadRenderer.LoadArt(); + RenderFunction renderFunction = [&](Art &art, SDL_Rect *src, SDL_Rect *dst) { + if (art.surface == nullptr) + return; + + if (SDL_BlitScaled(art.surface.get(), src, surface, dst) <= -1) + ErrSdl(); + }; + + Renderer.Render(renderFunction); +} + +void VirtualGamepadRenderer::LoadArt(SDL_Renderer *renderer) +{ + directionPadRenderer.LoadArt(renderer); const int Frames = 14; buttonArt.surface.reset(LoadPNG("ui_art\\button.png")); + if (buttonArt.surface == nullptr) + return; + buttonArt.logical_width = buttonArt.surface->w; buttonArt.frame_height = buttonArt.surface->h / Frames; buttonArt.frames = Frames; + + if (renderer != nullptr) { + buttonArt.texture.reset(SDL_CreateTextureFromSurface(renderer, buttonArt.surface.get())); + buttonArt.surface = nullptr; + } } -void VirtualDirectionPadRenderer::LoadArt() +void VirtualDirectionPadRenderer::LoadArt(SDL_Renderer *renderer) { - padSurface.reset(LoadPNG("ui_art\\directions.png")); - knobSurface.reset(LoadPNG("ui_art\\directions2.png")); + padArt.surface.reset(LoadPNG("ui_art\\directions.png")); + knobArt.surface.reset(LoadPNG("ui_art\\directions2.png")); + + if (renderer != nullptr) { + padArt.texture.reset(SDL_CreateTextureFromSurface(renderer, padArt.surface.get())); + padArt.surface = nullptr; + + knobArt.texture.reset(SDL_CreateTextureFromSurface(renderer, knobArt.surface.get())); + knobArt.surface = nullptr; + } } -void VirtualGamepadRenderer::Render(const Surface &out) +void VirtualGamepadRenderer::Render(RenderFunction renderFunction) { - directionPadRenderer.Render(out); - primaryActionButtonRenderer.Render(out); - secondaryActionButtonRenderer.Render(out); - spellActionButtonRenderer.Render(out); - cancelButtonRenderer.Render(out); + if (CurrentProc == DisableInputWndProc) + return; + + directionPadRenderer.Render(renderFunction); + primaryActionButtonRenderer.Render(renderFunction, buttonArt); + secondaryActionButtonRenderer.Render(renderFunction, buttonArt); + spellActionButtonRenderer.Render(renderFunction, buttonArt); + cancelButtonRenderer.Render(renderFunction, buttonArt); } -void VirtualDirectionPadRenderer::Render(const Surface &out) +void VirtualDirectionPadRenderer::Render(RenderFunction renderFunction) { - RenderPad(out); - RenderKnob(out); + RenderPad(renderFunction); + RenderKnob(renderFunction); } -void VirtualDirectionPadRenderer::RenderPad(const Surface &out) +void VirtualDirectionPadRenderer::RenderPad(RenderFunction renderFunction) { - if (padSurface == nullptr) - return; - auto center = virtualDirectionPad->area.position; auto radius = virtualDirectionPad->area.radius; int diameter = 2 * radius; @@ -104,14 +142,11 @@ void VirtualDirectionPadRenderer::RenderPad(const Surface &out) int width = diameter; int height = diameter; SDL_Rect rect { x, y, width, height }; - SDL_BlitScaled(padSurface.get(), nullptr, out.surface, &rect); + renderFunction(padArt, nullptr, &rect); } -void VirtualDirectionPadRenderer::RenderKnob(const Surface &out) +void VirtualDirectionPadRenderer::RenderKnob(RenderFunction renderFunction) { - if (knobSurface == nullptr) - return; - auto center = virtualDirectionPad->position; auto radius = virtualDirectionPad->area.radius / 3; int diameter = 2 * radius; @@ -121,17 +156,14 @@ void VirtualDirectionPadRenderer::RenderKnob(const Surface &out) int width = diameter; int height = diameter; SDL_Rect rect { x, y, width, height }; - SDL_BlitScaled(knobSurface.get(), nullptr, out.surface, &rect); + renderFunction(knobArt, nullptr, &rect); } -void VirtualPadButtonRenderer::Render(const Surface &out) +void VirtualPadButtonRenderer::Render(RenderFunction renderFunction, Art &buttonArt) { - if (buttonArt->surface == nullptr) - return; - VirtualGamepadButtonType buttonType = GetButtonType(); int frame = buttonType; - int offset = buttonArt->h() * frame; + int offset = buttonArt.h() * frame; auto center = virtualPadButton->area.position; auto radius = virtualPadButton->area.radius; @@ -142,9 +174,9 @@ void VirtualPadButtonRenderer::Render(const Surface &out) int width = diameter; int height = diameter; - SDL_Rect src { 0, offset, buttonArt->w(), buttonArt->h() }; + SDL_Rect src { 0, offset, buttonArt.w(), buttonArt.h() }; SDL_Rect dst { x, y, width, height }; - SDL_BlitScaled(buttonArt->surface.get(), &src, out.surface, &dst); + renderFunction(buttonArt, &src, &dst); } VirtualGamepadButtonType PrimaryActionButtonRenderer::GetButtonType() @@ -214,18 +246,18 @@ VirtualGamepadButtonType CancelButtonRenderer::GetButtonType() void VirtualGamepadRenderer::UnloadArt() { directionPadRenderer.UnloadArt(); - buttonArt.surface = nullptr; + buttonArt.Unload(); } void VirtualDirectionPadRenderer::UnloadArt() { - padSurface = nullptr; - knobSurface = nullptr; + padArt.Unload(); + knobArt.Unload(); } -void InitVirtualGamepadGFX() +void InitVirtualGamepadGFX(SDL_Renderer *renderer) { - Renderer.LoadArt(); + Renderer.LoadArt(renderer); } void FreeVirtualGamepadGFX() diff --git a/Source/controls/touch/renderers.h b/Source/controls/touch/renderers.h index c246d274d..8adbbf4ba 100644 --- a/Source/controls/touch/renderers.h +++ b/Source/controls/touch/renderers.h @@ -26,6 +26,8 @@ enum VirtualGamepadButtonType { GAMEPAD_BLANKDOWN, }; +typedef std::function RenderFunction; + class VirtualDirectionPadRenderer { public: VirtualDirectionPadRenderer(VirtualDirectionPad *virtualDirectionPad) @@ -33,42 +35,38 @@ public: { } - void LoadArt(); - void Render(const Surface &out); + void LoadArt(SDL_Renderer *renderer); + void Render(RenderFunction renderFunction); void UnloadArt(); private: VirtualDirectionPad *virtualDirectionPad; - SDLSurfaceUniquePtr padSurface; - SDLSurfaceUniquePtr knobSurface; + Art padArt; + Art knobArt; - void RenderPad(const Surface &out); - void RenderKnob(const Surface &out); + void RenderPad(RenderFunction renderFunction); + void RenderKnob(RenderFunction renderFunction); }; class VirtualPadButtonRenderer { public: - VirtualPadButtonRenderer(VirtualPadButton *virtualPadButton, Art *buttonArt) + VirtualPadButtonRenderer(VirtualPadButton *virtualPadButton) : virtualPadButton(virtualPadButton) - , buttonArt(buttonArt) { } - void Render(const Surface &out); + void Render(RenderFunction renderFunction, Art &buttonArt); protected: VirtualPadButton *virtualPadButton; virtual VirtualGamepadButtonType GetButtonType() = 0; - -private: - Art *buttonArt; }; class PrimaryActionButtonRenderer : public VirtualPadButtonRenderer { public: - PrimaryActionButtonRenderer(VirtualPadButton *primaryActionButton, Art *buttonArt) - : VirtualPadButtonRenderer(primaryActionButton, buttonArt) + PrimaryActionButtonRenderer(VirtualPadButton *primaryActionButton) + : VirtualPadButtonRenderer(primaryActionButton) { } @@ -81,8 +79,8 @@ private: class SecondaryActionButtonRenderer : public VirtualPadButtonRenderer { public: - SecondaryActionButtonRenderer(VirtualPadButton *secondaryActionButton, Art *buttonArt) - : VirtualPadButtonRenderer(secondaryActionButton, buttonArt) + SecondaryActionButtonRenderer(VirtualPadButton *secondaryActionButton) + : VirtualPadButtonRenderer(secondaryActionButton) { } @@ -92,8 +90,8 @@ private: class SpellActionButtonRenderer : public VirtualPadButtonRenderer { public: - SpellActionButtonRenderer(VirtualPadButton *spellActionButton, Art *buttonArt) - : VirtualPadButtonRenderer(spellActionButton, buttonArt) + SpellActionButtonRenderer(VirtualPadButton *spellActionButton) + : VirtualPadButtonRenderer(spellActionButton) { } @@ -103,8 +101,8 @@ private: class CancelButtonRenderer : public VirtualPadButtonRenderer { public: - CancelButtonRenderer(VirtualPadButton *cancelButton, Art *buttonArt) - : VirtualPadButtonRenderer(cancelButton, buttonArt) + CancelButtonRenderer(VirtualPadButton *cancelButton) + : VirtualPadButtonRenderer(cancelButton) { } @@ -116,15 +114,15 @@ class VirtualGamepadRenderer { public: VirtualGamepadRenderer(VirtualGamepad *virtualGamepad) : directionPadRenderer(&virtualGamepad->directionPad) - , primaryActionButtonRenderer(&virtualGamepad->primaryActionButton, &buttonArt) - , secondaryActionButtonRenderer(&virtualGamepad->secondaryActionButton, &buttonArt) - , spellActionButtonRenderer(&virtualGamepad->spellActionButton, &buttonArt) - , cancelButtonRenderer(&virtualGamepad->cancelButton, &buttonArt) + , primaryActionButtonRenderer(&virtualGamepad->primaryActionButton) + , secondaryActionButtonRenderer(&virtualGamepad->secondaryActionButton) + , spellActionButtonRenderer(&virtualGamepad->spellActionButton) + , cancelButtonRenderer(&virtualGamepad->cancelButton) { } - void LoadArt(); - void Render(const Surface &out); + void LoadArt(SDL_Renderer *renderer); + void Render(RenderFunction renderFunction); void UnloadArt(); private: @@ -136,9 +134,9 @@ private: Art buttonArt; }; -void DrawVirtualGamepad(const Surface &out); - -void InitVirtualGamepadGFX(); +void InitVirtualGamepadGFX(SDL_Renderer *renderer); +void RenderVirtualGamepad(SDL_Renderer *renderer); +void RenderVirtualGamepad(SDL_Surface *surface); void FreeVirtualGamepadGFX(); } // namespace devilution diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 0b36d703a..2f844e0e8 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1057,7 +1057,7 @@ void LoadAllGFX() { IncProgress(); #if defined(VIRTUAL_GAMEPAD) && !defined(USE_SDL1) - InitVirtualGamepadGFX(); + InitVirtualGamepadGFX(renderer); #endif IncProgress(); InitObjectGFX(); @@ -1861,7 +1861,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) } else { IncProgress(); #if defined(VIRTUAL_GAMEPAD) && !defined(USE_SDL1) - InitVirtualGamepadGFX(); + InitVirtualGamepadGFX(renderer); #endif IncProgress(); InitMissileGFX(gbIsHellfire); diff --git a/Source/dx.cpp b/Source/dx.cpp index a97482a26..6be844ee9 100644 --- a/Source/dx.cpp +++ b/Source/dx.cpp @@ -7,6 +7,7 @@ #include +#include "controls/touch/renderers.h" #include "engine.h" #include "options.h" #include "storm/storm.h" @@ -323,12 +324,18 @@ void RenderPresent() if (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) { ErrSdl(); } +#ifdef VIRTUAL_GAMEPAD + RenderVirtualGamepad(renderer); +#endif SDL_RenderPresent(renderer); if (!sgOptions.Graphics.bVSync) { LimitFrameRate(); } } else { +#ifdef VIRTUAL_GAMEPAD + RenderVirtualGamepad(surface); +#endif if (SDL_UpdateWindowSurface(ghMainWnd) <= -1) { ErrSdl(); } diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index a662c2998..bcada23e0 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1725,12 +1725,6 @@ void DrawAndBlit() DrawMain(hgt, ddsdesc, drawhpflag, drawmanaflag, drawsbarflag, drawbtnflag); -#if defined(VIRTUAL_GAMEPAD) && !defined(USE_SDL1) - SDL_Surface *sdlOutputSurface = GetOutputSurface(); - Surface outputSurface(sdlOutputSurface); - DrawVirtualGamepad(outputSurface); -#endif - RenderPresent(); drawhpflag = false;