Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1ac99e0
feat: 添加视频纹理支持及相关功能
BAKAOLC Feb 20, 2026
00b9331
feat: enhance video texture support with memory stream handling and r…
BAKAOLC Feb 21, 2026
6357b63
feat: add D3D11 video decoding support and multithreading enhancements
BAKAOLC Feb 21, 2026
775f53c
refactor: remove video support flag from D3D11 device creation
BAKAOLC Feb 22, 2026
e07f225
feat: enhance video decoding with frame rate handling and dynamic tol…
BAKAOLC Feb 22, 2026
5c7f96c
feat: add frame interval and fps calculation to video resource manage…
BAKAOLC Feb 22, 2026
47d25f8
feat: enhance video resource management with flexible loading options…
BAKAOLC Feb 22, 2026
c8b8a1a
feat: improve video decoding by adding resolution retry logic and adj…
BAKAOLC Feb 22, 2026
0994e4b
docs: update video loading example to simplify options description
BAKAOLC Feb 22, 2026
e8596d6
feat(video): add Lua bindings for video playback and stream management
BAKAOLC Feb 22, 2026
ccd6563
feat(video): add null checks and refactor video options parsing
BAKAOLC Feb 22, 2026
77dc3f0
feat(video): update hardware video decode configuration and frame rat…
BAKAOLC Feb 25, 2026
636fd5f
feat(video): remove Chinese comments and refactor error handling
BAKAOLC Feb 26, 2026
da4c51e
feat(video): extract video binding helpers and refactor decoder access
BAKAOLC Feb 26, 2026
7e1f875
feat(video): replace custom PropVariantGuard with WIL unique_prop_var…
BAKAOLC Feb 27, 2026
b357d30
feat(video): refactor Lua bindings to use lua::plus stack API
BAKAOLC Feb 27, 2026
3997055
feat(video): simplify type casting and remove unused pragma directives
BAKAOLC Feb 27, 2026
9896311
feat(video): simplify Lua binding table creation and remove unused in…
BAKAOLC Feb 27, 2026
97fcfbe
feat(resource): add video texture detection to resource interface
BAKAOLC Feb 27, 2026
eab182b
docs(video): add video API documentation and type definitions
BAKAOLC Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions LuaSTG/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ set(LUASTG_ENGINE_SOURCES
LuaSTG/LuaBinding/modern/SwapChain.cpp
LuaSTG/LuaBinding/modern/Texture2D.hpp
LuaSTG/LuaBinding/modern/Texture2D.cpp
LuaSTG/LuaBinding/modern/Video.hpp
LuaSTG/LuaBinding/modern/Video.cpp
LuaSTG/LuaBinding/VideoBindingHelpers.hpp
LuaSTG/LuaBinding/VideoBindingHelpers.cpp
LuaSTG/LuaBinding/modern/RenderTarget.hpp
LuaSTG/LuaBinding/modern/RenderTarget.cpp
LuaSTG/LuaBinding/modern/DepthStencilBuffer.hpp
Expand Down
2 changes: 2 additions & 0 deletions LuaSTG/LuaSTG/GameResource/Implement/ResourceTextureImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace luastg
core::IRenderTarget* GetRenderTarget() { return m_rt.get(); }
core::IDepthStencilBuffer* GetDepthStencilBuffer() { return m_ds.get(); }
bool IsRenderTarget() { return m_is_rendertarget; }
bool IsVideoTexture() { return m_texture && m_texture->isVideoTexture(); }
bool HasDepthStencilBuffer() { return m_enable_depthbuffer; }
public:
// 纹理容器
Expand All @@ -47,6 +48,7 @@ namespace luastg
core::IRenderTarget* GetRenderTarget() override { return m_rt.get(); }
core::IDepthStencilBuffer* GetDepthStencilBuffer() override { return m_ds.get(); }
bool IsRenderTarget() override { return true; }
bool IsVideoTexture() override { return false; }
bool HasDepthStencilBuffer() override { return !!m_ds; }

// RenderTargetStackResourceTextureImpl
Expand Down
13 changes: 8 additions & 5 deletions LuaSTG/LuaSTG/GameResource/ResourceDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,21 @@ namespace luastg
};
auto draw_texture = [](IResourceTexture* p_res, bool show_info, float scale) -> void
{
auto const size = p_res->GetTexture()->getSize();
auto* p_tex = p_res->GetTexture();
auto const size = p_tex->getSize();
if (show_info)
{
ImGui::Text("Size: %u x %u", size.x, size.y);
ImGui::Text("RenderTarget: %s", p_res->IsRenderTarget() ? "Yes" : "Not");
ImGui::Text("Dynamic: %s", p_res->IsRenderTarget() ? "Yes" : "Not");
unsigned long long mem_usage = size.x * size.y * 4;
char const* type_str = p_tex->isVideoTexture() ? "Video" : (p_res->IsRenderTarget() ? "RenderTarget" : "Texture");
ImGui::Text("Type: %s", type_str);
ImGui::Text("Dynamic: %s", p_tex->isDynamic() ? "Yes" : "Not");
unsigned long long display_mem = (unsigned long long)size.x * size.y * 4;
unsigned long long mem_usage = display_mem;
ImGui::Text("Adapter Memory Usage (Approximate): %s", bytes_count_to_string(mem_usage).c_str());
}
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, 1.0);
ImGui::Image(
reinterpret_cast<size_t>(p_res->GetTexture()->getNativeView()),
reinterpret_cast<size_t>(p_tex->getNativeView()),
ImVec2(scale * (float)size.x, scale * (float)size.y),
ImVec2(0.0f, 0.0f),
ImVec2(1.0f, 1.0f));
Expand Down
387 changes: 195 additions & 192 deletions LuaSTG/LuaSTG/GameResource/ResourceManager.h

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions LuaSTG/LuaSTG/GameResource/ResourcePool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "GameResource/Implement/ResourcePostEffectShaderImpl.hpp"
#include "GameResource/Implement/ResourceModelImpl.hpp"
#include "core/FileSystem.hpp"
#include "core/AudioEngine.hpp"
#include "AppFrame.h"
#include "lua/plus.hpp"

Expand Down Expand Up @@ -227,6 +228,47 @@ namespace luastg
return true;
}

bool ResourcePool::LoadVideo(const char* name, const char* path, core::VideoOpenOptions const* options) noexcept
{
if (m_TexturePool.find(std::string_view(name)) != m_TexturePool.end())
{
if (ResourceMgr::GetResourceLoadingLog())
{
spdlog::warn("[luastg] LoadVideo: 纹理 '{}' 已存在,加载操作已取消", name);
}
return true;
}

core::SmartReference<core::ITexture2D> p_texture;
bool ok = options
? LAPP.getGraphicsDevice()->createVideoTexture(path, *options, p_texture.put())
: LAPP.getGraphicsDevice()->createVideoTexture(path, p_texture.put());
if (!ok)
{
spdlog::error("[luastg] 从 '{}' 创建视频纹理 '{}' 失败", path, name);
return false;
}

try
{
core::SmartReference<IResourceTexture> tRes;
tRes.attach(new ResourceTextureImpl(name, p_texture.get()));
m_TexturePool.emplace(name, tRes);
}
catch (std::exception const& e)
{
spdlog::error("[luastg] LoadVideo: 创建视频纹理 '{}' 失败 ({})", name, e.what());
return false;
}

if (ResourceMgr::GetResourceLoadingLog())
{
spdlog::info("[luastg] LoadVideo: 已从 '{}' 加载视频 '{}' ({})", path, name, getResourcePoolTypeName());
}

return true;
}

bool ResourcePool::CreateTexture(const char* name, int width, int height) noexcept
{
if (m_TexturePool.find(std::string_view(name)) != m_TexturePool.end())
Expand Down
1 change: 1 addition & 0 deletions LuaSTG/LuaSTG/GameResource/ResourceTexture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace luastg
virtual core::IRenderTarget* GetRenderTarget() = 0;
virtual core::IDepthStencilBuffer* GetDepthStencilBuffer() = 0;
virtual bool IsRenderTarget() = 0;
virtual bool IsVideoTexture() = 0;
virtual bool HasDepthStencilBuffer() = 0;
};
};
Expand Down
135 changes: 135 additions & 0 deletions LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "LuaBinding/LuaWrapper.hpp"
#include "LuaBinding/VideoBindingHelpers.hpp"
#include "lua/plus.hpp"
#include "AppFrame.h"
#include "d3d11/VideoTexture.hpp"
#include "core/VideoDecoder.hpp"

void luastg::binding::ResourceManager::Register(lua_State* L) noexcept
{
Expand Down Expand Up @@ -52,6 +55,25 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept
return luaL_error(L, "can't load texture from file '%s'.", path);
return 0;
}
static int LoadVideo(lua_State* L) noexcept
{
lua::stack_t const ctx(L);
const char* name = luaL_checkstring(L, 1);
const char* path = luaL_checkstring(L, 2);

ResourcePool* pActivedPool = LRES.GetActivedPool();
if (!pActivedPool)
return luaL_error(L, "can't load resource at this time.");

core::VideoOpenOptions opt;
bool const has_options = ctx.index_of_top() >= 3 && ctx.is_table(3);
if (has_options)
video::parseVideoOptions(L, 3, opt);

if (!pActivedPool->LoadVideo(name, path, has_options ? &opt : nullptr))
return luaL_error(L, "can't load video from file '%s'.", path);
return 0;
}
static int LoadSprite(lua_State* L) noexcept
{
const char* name = luaL_checkstring(L, 1);
Expand Down Expand Up @@ -399,6 +421,14 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept
lua_pushboolean(L, p->IsRenderTarget());
return 1;
}
static int IsVideoTexture(lua_State* L) noexcept
{
core::SmartReference<IResourceTexture> p = LRES.FindTexture(luaL_checkstring(L, 1));
if (!p)
return luaL_error(L, "texture '%s' not found.", luaL_checkstring(L, 1));
lua_pushboolean(L, p->IsVideoTexture());
return 1;
}
static int SetTexturePreMulAlphaState(lua_State* L) noexcept
{
core::SmartReference<IResourceTexture> p = LRES.FindTexture(luaL_checkstring(L, 1));
Expand Down Expand Up @@ -671,13 +701,106 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept
LRES.CacheTTFFontString(luaL_checkstring(L, 1), str, len);
return 0;
}

// Video control functions

static int VideoSeek(lua_State* L) noexcept {
lua::stack_t const ctx(L);
const char* name = luaL_checkstring(L, 1);
double time = luaL_checknumber(L, 2);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found or is not a video texture.", name);
bool ok = decoder->seek(time);
ctx.push_value(ok);
return 1;
}

static int VideoSetLooping(lua_State* L) noexcept {
lua::stack_t const ctx(L);
const char* name = luaL_checkstring(L, 1);
bool loop = ctx.get_value<bool>(2);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found.", name);
decoder->setLooping(loop);
return 0;
}

static int VideoSetLoopRange(lua_State* L) noexcept {
const char* name = luaL_checkstring(L, 1);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found.", name);
double loop_end = luaL_checknumber(L, 2);
double loop_duration = luaL_checknumber(L, 3);
decoder->setLoopRange(loop_end, loop_duration);
return 0;
}

static int VideoUpdate(lua_State* L) noexcept {
lua::stack_t const ctx(L);
const char* name = luaL_checkstring(L, 1);
double time = luaL_checknumber(L, 2);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found or is not a video texture.", name);
bool ok = decoder->updateToTime(time);
ctx.push_value(ok);
return 1;
}

static int VideoGetInfo(lua_State* L) noexcept {
const char* name = luaL_checkstring(L, 1);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found.", name);
video::pushVideoInfoToLua(L, decoder);
return 1;
}

static int VideoGetVideoStreams(lua_State* L) noexcept {
const char* name = luaL_checkstring(L, 1);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found.", name);
video::pushVideoStreamsToLua(L, decoder);
return 1;
}

static int VideoGetAudioStreams(lua_State* L) noexcept {
const char* name = luaL_checkstring(L, 1);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found.", name);
video::pushAudioStreamsToLua(L, decoder);
return 1;
}

static int VideoReopen(lua_State* L) noexcept {
lua::stack_t const ctx(L);
const char* name = luaL_checkstring(L, 1);
auto decoder = video::getDecoderFromResourceName(name);
if (!decoder)
return luaL_error(L, "video texture '%s' not found or is not a video texture.", name);
core::VideoOpenOptions opt = decoder->getLastOpenOptions();
if (ctx.index_of_top() >= 2 && ctx.is_table(2))
video::parseVideoOptions(L, 2, opt);
if (!decoder->reopen(opt)) {
ctx.push_value(false);
return 1;
}
ctx.push_value(true);
return 1;
}
};

luaL_Reg const lib[] = {
{ "SetResLoadInfo", &Wrapper::SetResLoadInfo },
{ "SetResourceStatus", &Wrapper::SetResourceStatus },
{ "GetResourceStatus", &Wrapper::GetResourceStatus },
{ "LoadTexture", &Wrapper::LoadTexture },
{ "LoadVideo", &Wrapper::LoadVideo },
{ "LoadImage", &Wrapper::LoadSprite },
{ "LoadAnimation", &Wrapper::LoadAnimation },
{ "LoadPS", &Wrapper::LoadPS },
Expand All @@ -690,6 +813,7 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept
{ "LoadModel", &Wrapper::LoadModel },
{ "CreateRenderTarget", &Wrapper::CreateRenderTarget },
{ "IsRenderTarget", &Wrapper::IsRenderTarget },
{ "IsVideoTexture", &Wrapper::IsVideoTexture },
{ "SetTexturePreMulAlphaState", &Wrapper::SetTexturePreMulAlphaState },
{ "SetTextureSamplerState", &Wrapper::SetTextureSamplerState },
{ "GetTextureSize", &Wrapper::GetTextureSize },
Expand All @@ -710,6 +834,17 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept
{ "SetFontState", &Wrapper::SetFontState },

{ "CacheTTFString", &Wrapper::CacheTTFString },

// Video control functions
{ "VideoSeek", &Wrapper::VideoSeek },
{ "VideoSetLooping", &Wrapper::VideoSetLooping },
{ "VideoSetLoopRange", &Wrapper::VideoSetLoopRange },
{ "VideoUpdate", &Wrapper::VideoUpdate },
{ "VideoGetInfo", &Wrapper::VideoGetInfo },
{ "VideoGetVideoStreams", &Wrapper::VideoGetVideoStreams },
{ "VideoGetAudioStreams", &Wrapper::VideoGetAudioStreams },
{ "VideoReopen", &Wrapper::VideoReopen },

{ NULL, NULL },
};

Expand Down
2 changes: 2 additions & 0 deletions LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "LuaBinding/modern/Window.hpp"
#include "LuaBinding/modern/SwapChain.hpp"
#include "LuaBinding/modern/Texture2D.hpp"
#include "LuaBinding/modern/Video.hpp"
#include "LuaBinding/modern/RenderTarget.hpp"
#include "LuaBinding/modern/DepthStencilBuffer.hpp"
#include "LuaBinding/modern/Mesh.hpp"
Expand Down Expand Up @@ -82,6 +83,7 @@ namespace luastg::binding
Window_Windows11Extension::registerClass(L);
SwapChain::registerClass(L);
Texture2D::registerClass(L);
Video::registerClass(L);
RenderTarget::registerClass(L);
DepthStencilBuffer::registerClass(L);
Mesh::registerClass(L);
Expand Down
18 changes: 18 additions & 0 deletions LuaSTG/LuaSTG/LuaBinding/VideoBindingHelpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "VideoBindingHelpers.hpp"
#include "AppFrame.h"

namespace luastg::binding::video {
core::IVideoDecoder* getDecoderFromResourceName(const char* name) noexcept {
auto texture = LRES.FindTexture(name);
if (!texture) {
return nullptr;
}

auto texture2d = texture->GetTexture();
if (!texture2d) {
return nullptr;
}

return getDecoderFromTexture(texture2d);
}
}
Loading