Files
MosisUnreal/Plugins/MosisSDK/Source/MosisSDK/Private/MosisPhoneTexture.cpp

151 lines
4.4 KiB
C++

// Copyright OmixLab LTD. All Rights Reserved.
#include "MosisPhoneTexture.h"
#include "RenderingThread.h"
DEFINE_LOG_CATEGORY_STATIC(LogMosisPhoneTexture, Log, All);
UMosisPhoneTexture::UMosisPhoneTexture()
{
// UTexture2DDynamic defaults are fine
SRGB = true;
Filter = TF_Bilinear;
}
void UMosisPhoneTexture::Initialize(uint32 InWidth, uint32 InHeight)
{
UE_LOG(LogMosisPhoneTexture, Log, TEXT("Initialize: %dx%d"), InWidth, InHeight);
// Use UTexture2DDynamic's Init method
Init(InWidth, InHeight, PF_R8G8B8A8, false);
bIsReady = true;
}
#if PLATFORM_ANDROID
void UMosisPhoneTexture::UpdateFromHardwareBuffer(AHardwareBuffer* Buffer)
{
if (!Buffer)
{
UE_LOG(LogMosisPhoneTexture, Warning, TEXT("UpdateFromHardwareBuffer: null buffer"));
return;
}
CurrentBuffer = Buffer;
// Get buffer dimensions
AHardwareBuffer_Desc Desc{};
AHardwareBuffer_describe(Buffer, &Desc);
UE_LOG(LogMosisPhoneTexture, Log, TEXT("UpdateFromHardwareBuffer: %dx%d"), Desc.width, Desc.height);
// Lock buffer and read data
void* LockedData = nullptr;
int32 Result = AHardwareBuffer_lock(Buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, nullptr, &LockedData);
if (Result != 0 || !LockedData)
{
UE_LOG(LogMosisPhoneTexture, Error, TEXT("UpdateFromHardwareBuffer: Failed to lock buffer, result=%d"), Result);
return;
}
uint8* PixelData = static_cast<uint8*>(LockedData);
// Copy data to a buffer for update (accounting for stride)
uint32 StridePixels = Desc.stride > 0 ? Desc.stride : Desc.width;
TArray<uint8> TextureData;
TextureData.SetNumUninitialized(Desc.width * Desc.height * 4);
for (uint32 y = 0; y < Desc.height; y++)
{
FMemory::Memcpy(
TextureData.GetData() + y * Desc.width * 4,
PixelData + y * StridePixels * 4,
Desc.width * 4
);
}
AHardwareBuffer_unlock(Buffer, nullptr);
// Update the texture using UTexture2DDynamic's update regions
FTexture2DDynamicResource* TextureResource = static_cast<FTexture2DDynamicResource*>(GetResource());
if (TextureResource)
{
ENQUEUE_RENDER_COMMAND(UpdateMosisTexture)(
[TextureResource, Data = MoveTemp(TextureData), Width = Desc.width, Height = Desc.height](FRHICommandListImmediate& RHICmdList)
{
FUpdateTextureRegion2D Region(0, 0, 0, 0, Width, Height);
RHIUpdateTexture2D(
TextureResource->GetTexture2DRHI(),
0,
Region,
Width * 4,
Data.GetData()
);
}
);
}
}
void UMosisPhoneTexture::NotifyFrameAvailable()
{
if (!CurrentBuffer || !bIsReady)
{
return;
}
// Get buffer dimensions
AHardwareBuffer_Desc Desc{};
AHardwareBuffer_describe(CurrentBuffer, &Desc);
// Lock buffer and read data
void* LockedData = nullptr;
int32 Result = AHardwareBuffer_lock(CurrentBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, nullptr, &LockedData);
if (Result != 0 || !LockedData)
{
return;
}
uint8* PixelData = static_cast<uint8*>(LockedData);
// Copy data to a buffer for update (accounting for stride)
uint32 StridePixels = Desc.stride > 0 ? Desc.stride : Desc.width;
TArray<uint8> TextureData;
TextureData.SetNumUninitialized(Desc.width * Desc.height * 4);
for (uint32 y = 0; y < Desc.height; y++)
{
FMemory::Memcpy(
TextureData.GetData() + y * Desc.width * 4,
PixelData + y * StridePixels * 4,
Desc.width * 4
);
}
AHardwareBuffer_unlock(CurrentBuffer, nullptr);
// Update the texture
FTexture2DDynamicResource* TextureResource = static_cast<FTexture2DDynamicResource*>(GetResource());
if (TextureResource)
{
ENQUEUE_RENDER_COMMAND(UpdateMosisTextureFrame)(
[TextureResource, Data = MoveTemp(TextureData), Width = Desc.width, Height = Desc.height](FRHICommandListImmediate& RHICmdList)
{
FUpdateTextureRegion2D Region(0, 0, 0, 0, Width, Height);
RHIUpdateTexture2D(
TextureResource->GetTexture2DRHI(),
0,
Region,
Width * 4,
Data.GetData()
);
}
);
}
}
#endif // PLATFORM_ANDROID