Files
UnrealEngine/Engine/Source/Runtime/SlateRHIRenderer/Private/SlateRHITextureAtlas.cpp
2025-05-18 13:04:45 +08:00

102 lines
2.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SlateRHITextureAtlas.h"
#include "Textures/SlateTextureData.h"
#include "Rendering/SlateRenderer.h"
#include "RenderingThread.h"
#include "RenderUtils.h"
#include "Slate/SlateTextures.h"
/* FSlateTextureAtlasRHI structors
*****************************************************************************/
FSlateTextureAtlasRHI::FSlateTextureAtlasRHI( uint32 InWidth, uint32 InHeight, ESlateTextureAtlasPaddingStyle PaddingStyle, bool bUpdatesAfterInitialization)
: FSlateTextureAtlas(InWidth, InHeight, GPixelFormats[PF_B8G8R8A8].BlockBytes, PaddingStyle, bUpdatesAfterInitialization)
, AtlasTexture(new FSlateTexture2DRHIRef(InWidth, InHeight, PF_B8G8R8A8, NULL, TexCreate_SRGB, true))
{
}
FSlateTextureAtlasRHI::~FSlateTextureAtlasRHI( )
{
if (AtlasTexture != nullptr)
{
delete AtlasTexture;
}
}
FSlateShaderResource* FSlateTextureAtlasRHI::GetAtlasTexture() const
{
return AtlasTexture;
}
/* FSlateTextureAtlasRHI interface
*****************************************************************************/
void FSlateTextureAtlasRHI::ReleaseResources()
{
bNeedsUpdate = false;
BeginReleaseResource(AtlasTexture);
}
void FSlateTextureAtlasRHI::UpdateTexture_RenderThread( FSlateTextureData* RenderThreadData )
{
check(IsInRenderingThread());
if (!AtlasTexture->IsInitialized())
{
AtlasTexture->InitResource(FRHICommandListImmediate::Get());
}
check(AtlasTexture->IsInitialized());
const TArray<uint8>& RawBytes = RenderThreadData->GetRawBytes();
const uint8 * RawBytesPtr = RawBytes.GetData();
if ( RawBytesPtr != nullptr )
{
uint32 DestStride;
uint8* TempData = (uint8*)RHILockTexture2D(AtlasTexture->GetTypedResource(), 0, RLM_WriteOnly, /*out*/ DestStride, false);
// check(DestStride == (RenderThreadData->GetBytesPerPixel() * RenderThreadData->GetWidth())); // Temporarily disable check
if ( TempData != nullptr )
{
FMemory::Memcpy(TempData, RawBytesPtr, RenderThreadData->GetBytesPerPixel() * RenderThreadData->GetWidth() * RenderThreadData->GetHeight());
RHIUnlockTexture2D(AtlasTexture->GetTypedResource(), 0, false);
}
}
delete RenderThreadData;
}
/* FSlateTextureAtlas overrides
*****************************************************************************/
void FSlateTextureAtlasRHI::ConditionalUpdateTexture( )
{
checkSlow(IsThreadSafeForSlateRendering());
if (bNeedsUpdate)
{
// Copy the game thread data. This is deleted on the render thread
FSlateTextureData* RenderThreadData = new FSlateTextureData( AtlasWidth, AtlasHeight, BytesPerPixel, AtlasData );
FSlateTextureAtlasRHI* Atlas = this;
ENQUEUE_RENDER_COMMAND(SlateUpdateAtlasTextureCommand)(
[Atlas, RenderThreadData](FRHICommandListImmediate& RHICmdList)
{
Atlas->UpdateTexture_RenderThread( RenderThreadData );
});
bNeedsUpdate = false;
if (!bUpdatesAfterInitialization)
{
EmptyAtlasData();
}
}
}