191 lines
5.9 KiB
C++
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;
|
|
};
|