Files
TerracottaWarriors/Plugins/AndroidVulkanVideo_5.3/Source/AndroidVulkanVideo/Public/AndroidVulkanTextureSample.h
2025-07-14 22:24:27 +08:00

191 lines
5.9 KiB
C++

// ------------------------------------------------
// Copyright Joe Marshall 2024- All Rights Reserved
// ------------------------------------------------
//
// Vulkan texture sample - holds an opaque pointer
// to an Android AHardwareBuffer, and provides the
// IMediaTextureSample and
// IMediaTextureSampleConverter interfaces to allow
// Unreal's media player to show the frame.
// ------------------------------------------------
#pragma once
#include "IMediaTextureSample.h"
#include "IMediaTextureSampleConverter.h"
#include "MediaObjectPool.h"
#include "IVulkanVertexData.h"
#define TMP_REPLACE 5
class IVulkanImpl;
class AndroidVulkanTextureSample : public IMediaTextureSample,
public IMediaTextureSampleConverter,
public IMediaPoolable
{
friend class FAndroidVulkanTextureSamplePool;
public:
AndroidVulkanTextureSample();
void Init(IVulkanImpl *impl, void *hwImage, int w, int h, FMediaTimeStamp sampleTime);
void InitNoVideo();
~AndroidVulkanTextureSample();
virtual const void *GetBuffer() override
{
return NULL;
}
virtual FIntPoint GetDim() const override;
virtual FTimespan GetDuration() const override
{
return FTimespan::Zero();
}
virtual EMediaTextureSampleFormat GetFormat() const override
{
return VideoTextureFormat;
}
virtual FIntPoint GetOutputDim() const override;
virtual uint32 GetStride() const override;
virtual FRHITexture *GetTexture() const override;
virtual IMediaTextureSampleConverter *GetMediaTextureSampleConverter() override;
virtual FMediaTimeStamp GetTime() const;
virtual bool IsCacheable() const
{
return true;
}
virtual bool IsOutputSrgb() const
{
return false;
}
// IMediaTextureSampleConverter interface (changed in 5.5 to add command list)
virtual bool Convert(FTexture2DRHIRef &InDstTexture, const FConversionHints &Hints);
bool ConvertInternal(FRHICommandListImmediate &RHICmdList, FTexture2DRHIRef &InDstTexture,
const FConversionHints &Hints);
// called inside render pass
bool RenderToMesh(FTexture2DRHIRef InDstTexture, FRHICommandList &RHICmdList, void *MeshID);
// called outside a render pass
// n.b. don't make matrices etc. const references
// because then we get dangling references and
// BAD THINGS happen
bool UpdateViewMatrices(FTexture2DRHIRef InDstTexture, FRHICommandList &RHICmdList,
ShaderViewMatrices Matrices, void *MeshID);
bool InitFrameForMeshRendering(FTexture2DRHIRef InDstTexture, FRHICommandList &RHICmdList,
void *MeshID);
bool UpdateMesh(FTexture2DRHIRef InDstTexture, FRHICommandList &RHICmdList,
TArray<VertexData> PositionAndUV, TArray<uint32> Indices,
ShaderModelMatrix Matrix, void *MeshID);
void InitializePoolable() override;
virtual bool IsReadyForReuse() override;
virtual void ShutdownPoolable() override;
void Clear();
void ClearIfShown();
static void SetVideoFormat(EMediaTextureSampleFormat Format)
{
VideoTextureFormat = Format;
}
void ImplDeleted();
private:
void FRenderOnRHIThreadCommand(const FTexture2DRHIRef &DstTexture);
void FRenderMeshOnRHIThreadCommand(const FTexture2DRHIRef &DstTexture, void *MeshID,
int Samples);
void FUpdateMeshOnRHIThreadCommand(const FTexture2DRHIRef &DstTexture,
const TArray<VertexData> &PositionAndUV,
const TArray<uint32> &Indices,
const ShaderModelMatrix &Matrix, void *MeshID);
void FUpdateMatricesOnRHIThreadCommand(const FTexture2DRHIRef &DstTexture,
const ShaderViewMatrices &Matrices, void *MeshID);
void FInitMeshRenderingCommand(const FTexture2DRHIRef &DstTexture, void *MeshID, int Samples);
bool IsEmptyTexture;
FGPUFenceRHIRef Fence;
FIntPoint Dimension;
void *FrameHWImage;
/** Duration for which the sample is valid. */
// FTimespan TimeDuration;
/** Sample time. */
FMediaTimeStamp SampleTime;
int NumSamples; // number of samples used for MSAA on rendering meshes directly
IVulkanImpl *Impl;
bool Shown;
FCriticalSection AccessLock;
static EMediaTextureSampleFormat VideoTextureFormat;
};
class FAndroidVulkanTextureSamplePool : public TMediaObjectPool<AndroidVulkanTextureSample>
{
public:
void Tick()
{
TMediaObjectPool<AndroidVulkanTextureSample>::Tick();
for (auto wp : liveObjects)
{
auto pin = wp.Pin();
if (pin.IsValid())
{
pin->ClearIfShown();
}
}
}
TSharedRef<AndroidVulkanTextureSample, ESPMode::ThreadSafe> AcquireShared()
{
auto ret = TMediaObjectPool<AndroidVulkanTextureSample>::AcquireShared();
TWeakPtr<AndroidVulkanTextureSample, ESPMode::ThreadSafe> wp = ret;
if (!liveObjects.Find(wp))
{
liveObjects.Add(wp);
}
return ret;
}
void ReleaseEverything()
{
for (auto wp : liveObjects)
{
auto pin = wp.Pin();
if (pin.IsValid())
{
pin->ImplDeleted();
}
}
for (auto wp : liveObjects)
{
auto pin = wp.Pin();
if (pin.IsValid())
{
pin->ShutdownPoolable();
}
}
Reset();
}
int bob[TMP_REPLACE];
// for anything that has already been drawn, we want to release textures ASAP,
// rather than whenever Unreal gets round to it.
TArray<TWeakPtr<AndroidVulkanTextureSample, ESPMode::ThreadSafe>> liveObjects;
};