Files
UnrealEngine/Engine/Plugins/Media/BinkMedia/Source/BinkMediaPlayer/Private/binktexturesRHI.cpp
2025-05-18 13:04:45 +08:00

590 lines
22 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#define BINKRHIFUNCTIONS
#define BINKTEXTURESCLEANUP
#include "egttypes.h"
#include "binktiny.h"
#include "binktextures.h"
#include "BinkShaders.h"
#include "PipelineStateCache.h"
#include "RHIStaticStates.h"
#include "RenderGraphBuilder.h"
#include "RenderingThread.h"
extern FRHITexture *BinkRHIRenderTarget;
extern ERenderTargetLoadAction BinkRenderTargetLoadAction;
FRDGTextureRef BinkRegisterExternalTexture(FRDGBuilder& GraphBuilder, FRHITexture* Texture, const TCHAR* NameIfUnregistered)
{
if (FRDGTextureRef FoundTexture = GraphBuilder.FindExternalTexture(Texture))
{
return FoundTexture;
}
return GraphBuilder.RegisterExternalTexture(CreateRenderTarget(Texture, NameIfUnregistered));
}
typedef struct BINKSHADERSRHI
{
BINKSHADERS pub;
} BINKSHADERSRHI;
typedef struct BINKTEXTURESRHI
{
BINKTEXTURES pub;
// RHI
S32 video_width, video_height;
S32 dirty;
BINKSHADERSRHI * shaders;
HBINK bink;
// this is the Bink info on the textures
BINKFRAMEBUFFERS bink_buffers;
F32 Ax, Ay, Bx, By, Cx, Cy;
F32 alpha;
S32 draw_type;
S32 draw_flags;
F32 u0, v0, u1, v1;
FTextureRHIRef Ytexture[BINKMAXFRAMEBUFFERS];
FTextureRHIRef cRtexture[BINKMAXFRAMEBUFFERS];
FTextureRHIRef cBtexture[BINKMAXFRAMEBUFFERS];
FTextureRHIRef Atexture[BINKMAXFRAMEBUFFERS];
FTextureRHIRef Htexture[BINKMAXFRAMEBUFFERS];
// unused for now
S32 tonemap;
F32 exposure;
F32 out_luma;
} BINKTEXTURESRHI;
#if defined( BINKTEXTURESINDIRECTBINKCALLS )
RADDEFFUNC void indirectBinkGetFrameBuffersInfo( HBINK bink, BINKFRAMEBUFFERS * fbset );
#define BinkGetFrameBuffersInfo indirectBinkGetFrameBuffersInfo
RADDEFFUNC void indirectBinkRegisterFrameBuffers( HBINK bink, BINKFRAMEBUFFERS * fbset );
#define BinkRegisterFrameBuffers indirectBinkRegisterFrameBuffers
RADDEFFUNC S32 indirectBinkAllocateFrameBuffers( HBINK bp, BINKFRAMEBUFFERS * set, U32 minimum_alignment );
#define BinkAllocateFrameBuffers indirectBinkAllocateFrameBuffers
RADDEFFUNC void * indirectBinkUtilMalloc(U64 bytes);
#define BinkUtilMalloc indirectBinkUtilMalloc
RADDEFFUNC void indirectBinkUtilFree(void * ptr);
#define BinkUtilFree indirectBinkUtilFree
#endif
static BINKTEXTURES * Create_textures( BINKSHADERS * pshaders, HBINK bink, void * user_ptr );
static void Free_shaders( BINKSHADERS * pshaders );
static void Free_textures( BINKTEXTURES * ptextures );
static void Start_texture_update( BINKTEXTURES * ptextures );
static void Finish_texture_update( BINKTEXTURES * ptextures );
static void Draw_textures( BINKTEXTURES * ptextures, BINKSHADERS * pshaders, void * graphics_context );
static void Set_draw_position( BINKTEXTURES * ptextures, F32 x0, F32 y0, F32 x1, F32 y1 );
static void Set_draw_corners( BINKTEXTURES * ptextures, F32 Ax, F32 Ay, F32 Bx, F32 By, F32 Cx, F32 Cy );
static void Set_source_rect( BINKTEXTURES * ptextures, F32 u0, F32 v0, F32 u1, F32 v1 );
static void Set_alpha_settings( BINKTEXTURES * ptextures, F32 alpha_value, S32 draw_type );
static void Set_hdr_settings( BINKTEXTURES * ptextures, S32 tonemap, F32 exposure, S32 out_nits );
//-----------------------------------------------------------------------------
RADDEFFUNC BINKSHADERS * Create_Bink_shaders(void * dummy_device)
{
BINKSHADERSRHI * pshaders;
pshaders = (BINKSHADERSRHI*)FMemory::Malloc(sizeof(*pshaders));
if (pshaders == 0)
{
return 0;
}
FMemory::Memset(pshaders, 0, sizeof(*pshaders));
pshaders->pub.Create_textures = Create_textures;
pshaders->pub.Free_shaders = Free_shaders;
return &pshaders->pub;
}
//-----------------------------------------------------------------------------
static void Free_shaders( BINKSHADERS * pshaders )
{
FMemory::Free(pshaders);
}
//-----------------------------------------------------------------------------
static BINKTEXTURES * Create_textures(BINKSHADERS * pshaders, HBINK bink, void * user_ptr)
{
BINKTEXTURESRHI * textures;
BINKFRAMEBUFFERS * bb;
textures = (BINKTEXTURESRHI *)FMemory::Malloc(sizeof(*textures));
if (textures == 0)
return 0;
FMemory::Memset(textures, 0, sizeof(*textures));
textures->pub.user_ptr = user_ptr;
textures->shaders = (BINKSHADERSRHI*)pshaders;
textures->bink = bink;
textures->video_width = bink->Width;
textures->video_height = bink->Height;
bb = &textures->bink_buffers;
BinkGetFrameBuffersInfo(bink, bb);
#if !PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
// allocate the system memory buffers if not allocated
if (!BinkAllocateFrameBuffers(bink, bb, 0))
{
FMemory::Free(textures);
return 0;
}
#endif
FRHICommandListImmediate& RHICmdList = FRHICommandListImmediate::Get();
EPixelFormat format = PF_R8;
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
ETextureCreateFlags TexCreateFlags = TexCreate_CPUReadback | TexCreate_CPUWritable | TexCreate_OfflineProcessed | TexCreate_NoTiling;
#else
ETextureCreateFlags TexCreateFlags = TexCreate_NoTiling;
#endif
const FRHITextureCreateDesc YADesc =
FRHITextureCreateDesc::Create2D(TEXT("BINK"), bb->YABufferWidth, bb->YABufferHeight, format)
.SetFlags(TexCreateFlags);
const FRHITextureCreateDesc cRcBDesc =
FRHITextureCreateDesc::Create2D(TEXT("BINK"), bb->cRcBBufferWidth, bb->cRcBBufferHeight, format)
.SetFlags(TexCreateFlags);
for (int i = 0; i < bb->TotalFrames; ++i)
{
BINKFRAMEPLANESET *bp_src = &bb->Frames[i];
if (bp_src->YPlane.Allocate)
{
textures->Ytexture[i] = RHICreateTexture(YADesc);
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
bp_src->YPlane.Buffer = RHICmdList.LockTexture2D(textures->Ytexture[i], 0, PLATFORM_DIRECT_TEXTURE_MEMORY_ACCESS_LOCK_MODE, bp_src->YPlane.BufferPitch, false, false);
bp_src->YPlane.BufferPitch = bp_src->YPlane.BufferPitch ? bp_src->YPlane.BufferPitch : ((bb->YABufferWidth+255)&-256);
#endif
}
if (bp_src->cRPlane.Allocate)
{
textures->cRtexture[i] = RHICreateTexture(cRcBDesc);
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
bp_src->cRPlane.Buffer = RHICmdList.LockTexture2D(textures->cRtexture[i], 0, PLATFORM_DIRECT_TEXTURE_MEMORY_ACCESS_LOCK_MODE, bp_src->cRPlane.BufferPitch, false, false);
bp_src->cRPlane.BufferPitch = bp_src->cRPlane.BufferPitch ? bp_src->cRPlane.BufferPitch : ((bb->cRcBBufferWidth+255)&-256);
#endif
}
if (bp_src->cBPlane.Allocate)
{
textures->cBtexture[i] = RHICreateTexture(cRcBDesc);
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
bp_src->cBPlane.Buffer = RHICmdList.LockTexture2D(textures->cBtexture[i], 0, PLATFORM_DIRECT_TEXTURE_MEMORY_ACCESS_LOCK_MODE, bp_src->cBPlane.BufferPitch, false, false);
bp_src->cBPlane.BufferPitch = bp_src->cBPlane.BufferPitch ? bp_src->cBPlane.BufferPitch : ((bb->cRcBBufferWidth+255)&-256);
#endif
}
if (bp_src->APlane.Allocate)
{
textures->Atexture[i] = RHICreateTexture(YADesc);
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
bp_src->APlane.Buffer = RHICmdList.LockTexture2D(textures->Atexture[i], 0, PLATFORM_DIRECT_TEXTURE_MEMORY_ACCESS_LOCK_MODE, bp_src->APlane.BufferPitch, false, false);
bp_src->APlane.BufferPitch = bp_src->APlane.BufferPitch ? bp_src->APlane.BufferPitch : ((bb->YABufferWidth+255)&-256);
#endif
}
if (bp_src->HPlane.Allocate)
{
textures->Htexture[i] = RHICreateTexture(YADesc);
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
bp_src->HPlane.Buffer = RHICmdList.LockTexture2D(textures->Htexture[i], 0, PLATFORM_DIRECT_TEXTURE_MEMORY_ACCESS_LOCK_MODE, bp_src->HPlane.BufferPitch, false, false);
bp_src->HPlane.BufferPitch = bp_src->HPlane.BufferPitch ? bp_src->HPlane.BufferPitch : ((bb->YABufferWidth+255)&-256);
#endif
}
}
// Register our locked texture pointers with Bink
BinkRegisterFrameBuffers(bink, bb);
Set_draw_corners(&textures->pub, 0, 0, 1, 0, 0, 1);
Set_source_rect(&textures->pub, 0, 0, 1, 1);
Set_alpha_settings(&textures->pub, 1, 0);
Set_hdr_settings(&textures->pub, 0, 1.0f, 80);
textures->pub.Free_textures = Free_textures;
textures->pub.Start_texture_update = Start_texture_update;
textures->pub.Finish_texture_update = Finish_texture_update;
textures->pub.Draw_textures = Draw_textures;
textures->pub.Set_draw_position = Set_draw_position;
textures->pub.Set_draw_corners = Set_draw_corners;
textures->pub.Set_source_rect = Set_source_rect;
textures->pub.Set_alpha_settings = Set_alpha_settings;
textures->pub.Set_hdr_settings = Set_hdr_settings;
return &textures->pub;
}
//-----------------------------------------------------------------------------
static void Free_textures(BINKTEXTURES* ptextures)
{
FRHICommandListImmediate& RHICmdList = FRHICommandListImmediate::Get();
BINKTEXTURESRHI* textures = (BINKTEXTURESRHI*)ptextures;
BINKFRAMEBUFFERS *bb = &textures->bink_buffers;
/*
RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThreadFlushResources);
RHIFlushResources();
RHICmdList.SubmitCommandsHint();
FPlatformMisc::MemoryBarrier();
*/
for (int i = 0; i < bb->TotalFrames; ++i)
{
BINKFRAMEPLANESET *bp_src = &bb->Frames[i];
#if PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
if (bp_src->YPlane.Buffer) RHICmdList.UnlockTexture2D(textures->Ytexture[i], 0, false);
if (bp_src->cRPlane.Buffer) RHICmdList.UnlockTexture2D(textures->cRtexture[i], 0, false);
if (bp_src->cBPlane.Buffer) RHICmdList.UnlockTexture2D(textures->cBtexture[i], 0, false);
if (bp_src->APlane.Buffer) RHICmdList.UnlockTexture2D(textures->Atexture[i], 0, false);
if (bp_src->HPlane.Buffer) RHICmdList.UnlockTexture2D(textures->Htexture[i], 0, false);
#endif
if (textures->Ytexture[i].IsValid()) textures->Ytexture[i].SafeRelease();
if (textures->cRtexture[i].IsValid()) textures->cRtexture[i].SafeRelease();
if (textures->cBtexture[i].IsValid()) textures->cBtexture[i].SafeRelease();
if (textures->Atexture[i].IsValid()) textures->Atexture[i].SafeRelease();
if (textures->Htexture[i].IsValid()) textures->Htexture[i].SafeRelease();
}
FMemory::Free(textures);
}
static void Start_texture_update( BINKTEXTURES * ptextures )
{
//BINKTEXTURESRHI *textures = (BINKTEXTURESRHI*)ptextures;
}
static void Finish_texture_update( BINKTEXTURES * ptextures )
{
BINKTEXTURESRHI * textures = (BINKTEXTURESRHI*)ptextures;
BINKFRAMEBUFFERS *bb = &textures->bink_buffers;
int frame_num = bb->FrameNum;
BINKFRAMEPLANESET *bp_src = &bb->Frames[frame_num];
#if !PLATFORM_HAS_DIRECT_TEXTURE_MEMORY_ACCESS
textures->dirty = 1;
#endif
textures->pub.Ytexture = (void*)(UINTa)&textures->Ytexture[frame_num];
textures->pub.cRtexture = (void*)(UINTa)&textures->cRtexture[frame_num];
textures->pub.cBtexture = (void*)(UINTa)&textures->cBtexture[frame_num];
textures->pub.Atexture = (void*)(UINTa)&textures->Atexture[frame_num];
textures->pub.Htexture = (void*)(UINTa)&textures->Htexture[frame_num];
}
//-----------------------------------------------------------------------------
static void update_plane_texture_rect(FRHICommandListImmediate& RHI, FRHITexture* RHITexture, BINKPLANE const* plane, unsigned w, unsigned h)
{
uint32 Stride = 0;
unsigned char* TextureMemory = (unsigned char*)RHI.LockTexture2D(RHITexture, 0, RLM_WriteOnly, Stride, false);
if (TextureMemory)
{
check(Stride >= w);
if (Stride == w)
{
FMemory::Memcpy(TextureMemory, plane->Buffer, w * h);
}
else
{
for (unsigned i = 0; i < h; ++i)
{
FMemory::Memcpy(TextureMemory + i * Stride, (char*)plane->Buffer + i * w, w);
}
}
RHI.UnlockTexture2D(RHITexture, 0, false);
}
}
static void Draw_textures(BINKTEXTURES* ptextures, BINKSHADERS* pshaders, void* graphics_context)
{
BINKTEXTURESRHI* textures = (BINKTEXTURESRHI*)ptextures;
BINKSHADERSRHI* bshaders = (BINKSHADERSRHI*)pshaders;
BINKFRAMEBUFFERS *bb = &textures->bink_buffers;
int frame_num = bb->FrameNum;
BINKFRAMEPLANESET *bp_src = &bb->Frames[frame_num];
// nowhere to render to?
if (BinkRHIRenderTarget == 0)
return;
if (bshaders == 0)
bshaders = textures->shaders;
int hasAPlane = bp_src->APlane.Allocate;
int hasHPlane = bp_src->HPlane.Allocate;
FRDGBuilder BinkGraphBuilder(FRHICommandListImmediate::Get());
FBinkParameters *consts = BinkGraphBuilder.AllocParameters<FBinkParameters>();
FRDGTexture *BinkRDGTexture = BinkRegisterExternalTexture(BinkGraphBuilder, BinkRHIRenderTarget, TEXT("Bink_RT"));
consts->RenderTargets[0] = FRenderTargetBinding(BinkRDGTexture, BinkRenderTargetLoadAction, 0);
consts->tex0 = BinkRegisterExternalTexture(BinkGraphBuilder, textures->Ytexture[frame_num], TEXT("BinkY"));
consts->tex1 = BinkRegisterExternalTexture(BinkGraphBuilder, textures->cRtexture[frame_num], TEXT("BinkCr"));
consts->tex2 = BinkRegisterExternalTexture(BinkGraphBuilder, textures->cBtexture[frame_num], TEXT("BinkCb"));
consts->tex3 = BinkRegisterExternalTexture(BinkGraphBuilder, hasAPlane ? textures->Atexture[frame_num] : textures->Ytexture[frame_num], TEXT("BinkA"));
consts->tex4 = BinkRegisterExternalTexture(BinkGraphBuilder, hasHPlane ? textures->Htexture[frame_num] : textures->Ytexture[frame_num], TEXT("BinkH"));
consts->samp0 = TStaticSamplerState<SF_Bilinear>::GetRHI();
consts->samp1 = TStaticSamplerState<SF_Bilinear>::GetRHI();
consts->samp2 = TStaticSamplerState<SF_Bilinear>::GetRHI();
consts->samp3 = TStaticSamplerState<SF_Bilinear>::GetRHI();
consts->samp4 = TStaticSamplerState<SF_Bilinear>::GetRHI();
// Pixel shader alpha constants
if (textures->draw_type == 3)
{
unsigned BinkColorA = 0xffffffff;
unsigned BinkColorB = 0xffc0c0c0;
consts->consta.X = ((F32)(S32)((BinkColorA >> 0) & 255)) * (1.0f / 255.0f);
consts->consta.Y = ((F32)(S32)((BinkColorA >> 8) & 255)) * (1.0f / 255.0f);
consts->consta.Z = ((F32)(S32)((BinkColorA >> 16) & 255)) * (1.0f / 255.0f);
consts->consta.W = ((F32)(S32)((BinkColorA >> 24) & 255)) * (1.0f / 255.0f);
consts->crc.X = ((F32)(S32)((BinkColorB >> 0) & 255)) * (1.0f / 255.0f);
consts->crc.Y = ((F32)(S32)((BinkColorB >> 8) & 255)) * (1.0f / 255.0f);
consts->crc.Z = ((F32)(S32)((BinkColorB >> 16) & 255)) * (1.0f / 255.0f);
consts->crc.W = ((F32)(S32)((BinkColorB >> 24) & 255)) * (1.0f / 255.0f);
consts->cbc.X = ((F32)textures->bink->Width) / 8.0f;
consts->cbc.Y = ((F32)textures->bink->Height) / 8.0f;
consts->cbc.Z = 0.f;
consts->cbc.W = 0.f;
}
else
{
// Pixel shader alpha constants
consts->consta.Z = consts->consta.Y = consts->consta.X = textures->draw_type == 1 ? textures->alpha : 1.0f;
consts->consta.W = textures->alpha;
if (hasHPlane)
{
// HDR stuff
consts->crc.X = textures->bink->ColorSpace[0];
consts->crc.Y = textures->exposure;
consts->crc.Z = textures->out_luma;
consts->crc.W = 0;
consts->cbc.X = textures->bink->ColorSpace[1];
consts->cbc.Y = textures->bink->ColorSpace[2];
consts->cbc.Z = textures->bink->ColorSpace[3];
consts->cbc.W = textures->bink->ColorSpace[4];
}
else
{
// set the constants for the type of ycrcb we have
consts->crc.X = textures->bink->ColorSpace[0];
consts->crc.Y = textures->bink->ColorSpace[1];
consts->crc.Z = textures->bink->ColorSpace[2];
consts->crc.W = textures->bink->ColorSpace[3];
consts->cbc.X = textures->bink->ColorSpace[4];
consts->cbc.Y = textures->bink->ColorSpace[5];
consts->cbc.Z = textures->bink->ColorSpace[6];
consts->cbc.W = textures->bink->ColorSpace[7];
consts->adj.X = textures->bink->ColorSpace[8];
consts->adj.Y = textures->bink->ColorSpace[9];
consts->adj.Z = textures->bink->ColorSpace[10];
consts->adj.W = textures->bink->ColorSpace[11];
consts->yscale.X = textures->bink->ColorSpace[12];
consts->yscale.Y = textures->bink->ColorSpace[13];
consts->yscale.Z = textures->bink->ColorSpace[14];
consts->yscale.W = textures->bink->ColorSpace[15];
}
}
// Vertex shader constants
consts->xy_xform0.X = (textures->Bx - textures->Ax) * 2.0f;
consts->xy_xform0.Y = (textures->Cx - textures->Ax) * 2.0f;
consts->xy_xform0.Z = (textures->By - textures->Ay) * -2.0f;
consts->xy_xform0.W = (textures->Cy - textures->Ay) * -2.0f; // view space has +y = up, our coords have +y = down
consts->xy_xform1.X = textures->Ax * 2.0f - 1.0f;
consts->xy_xform1.Y = 1.0f - textures->Ay * 2.0f;
consts->xy_xform1.Z = 0.0f;
consts->xy_xform1.W = 0.0f;
// UV matrix
{
F32 luma_u_scale = (F32)textures->video_width / (F32)bb->YABufferWidth;
F32 luma_v_scale = (F32)textures->video_height / (F32)bb->YABufferHeight;
F32 chroma_u_scale = (F32)(textures->video_width / 2) / (F32)bb->cRcBBufferWidth;
F32 chroma_v_scale = (F32)(textures->video_height / 2) / (F32)bb->cRcBBufferHeight;
// Set up matrix columns for UV transform (currently just scale+translate, could add rotation)
// X column
consts->uv_xform0.X = (textures->u1 - textures->u0) * luma_u_scale;
consts->uv_xform0.Y = 0.0f;
consts->uv_xform0.Z = (textures->u1 - textures->u0) * chroma_u_scale;
consts->uv_xform0.W = 0.0f;
// Y column
consts->uv_xform1.X = 0.0f;
consts->uv_xform1.Y = (textures->v1 - textures->v0) * luma_v_scale;
consts->uv_xform1.Z = 0.0f;
consts->uv_xform1.W = (textures->v1 - textures->v0) * chroma_v_scale;
// W column (translation)
consts->uv_xform2.X = textures->u0 * luma_u_scale;
consts->uv_xform2.Y = textures->v0 * luma_v_scale;
consts->uv_xform2.Z = textures->u0 * chroma_u_scale;
consts->uv_xform2.W = textures->v0 * chroma_v_scale;
}
FBinkDrawVS::FParameters* vert_params = BinkGraphBuilder.AllocParameters<FBinkDrawVS::FParameters>();
vert_params->BinkParameters = *consts;
FBinkDrawICtCpPS::FParameters* ictcp_params = BinkGraphBuilder.AllocParameters<FBinkDrawICtCpPS::FParameters>();
ictcp_params->BinkParameters = *consts;
FBinkDrawYCbCrPS::FParameters* ycbcr_params = BinkGraphBuilder.AllocParameters<FBinkDrawYCbCrPS::FParameters>();
ycbcr_params->BinkParameters = *consts;
auto* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel);
TShaderMapRef<FBinkDrawVS> DrawVS(ShaderMap);
FBinkDrawICtCpPS::FPermutationDomain ictcp_pv;
ictcp_pv.Set<FBinkDrawICtCpPS::FALPHA>(!!hasAPlane);
ictcp_pv.Set<FBinkDrawICtCpPS::FTONEMAP>(textures->tonemap == 1);
ictcp_pv.Set<FBinkDrawICtCpPS::FST2084>(textures->tonemap == 2);
TShaderMapRef<FBinkDrawICtCpPS> DrawICtCpPS(ShaderMap, ictcp_pv);
FBinkDrawYCbCrPS::FPermutationDomain ycbcr_pv;
ycbcr_pv.Set<FBinkDrawYCbCrPS::FALPHA>(!!hasAPlane);
ycbcr_pv.Set<FBinkDrawYCbCrPS::FSRGB>(!!(textures->draw_flags & 0x80000000));
TShaderMapRef<FBinkDrawYCbCrPS> DrawYCbCrPS(ShaderMap, ycbcr_pv);
FRDGEventName EventName(TEXT("Bink"));
BinkGraphBuilder.AddPass(
MoveTemp(EventName),
consts,
ERDGPassFlags::Raster,
[&](FRHICommandListImmediate& RHICmdList)
{
if (textures->dirty)
{
textures->dirty = 0;
FUpdateTextureRegion2D region_YAH(0, 0, 0, 0, bb->YABufferWidth, bb->YABufferHeight);
FUpdateTextureRegion2D region_cRcB(0, 0, 0, 0, bb->cRcBBufferWidth, bb->cRcBBufferHeight);
RHICmdList.UpdateTexture2D(textures->Ytexture[frame_num], 0, region_YAH, bp_src->YPlane.BufferPitch, (uint8*)bp_src->YPlane.Buffer);
RHICmdList.UpdateTexture2D(textures->cRtexture[frame_num], 0, region_cRcB, bp_src->cRPlane.BufferPitch, (uint8*)bp_src->cRPlane.Buffer);
RHICmdList.UpdateTexture2D(textures->cBtexture[frame_num], 0, region_cRcB, bp_src->cBPlane.BufferPitch, (uint8*)bp_src->cBPlane.Buffer);
if (hasAPlane) RHICmdList.UpdateTexture2D(textures->Atexture[frame_num], 0, region_YAH, bp_src->APlane.BufferPitch, (uint8*)bp_src->APlane.Buffer);
if (hasHPlane) RHICmdList.UpdateTexture2D(textures->Htexture[frame_num], 0, region_YAH, bp_src->HPlane.BufferPitch, (uint8*)bp_src->HPlane.Buffer);
}
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
// Set up blending
if ((!hasAPlane && textures->alpha >= 0.999f) || textures->draw_type == 2)
{
// opaque
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
}
else if (textures->draw_type == 1)
{
// alpha pre-multiplied
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_InverseSourceAlpha, BO_Add, BF_One, BF_Zero>::GetRHI();
}
else
{
// normal alpha
GraphicsPSOInit.BlendState = TStaticBlendState<CW_RGBA, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha, BO_Add, BF_One, BF_Zero>::GetRHI();
}
// Disable backface culling
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None, ERasterizerDepthClipMode::DepthClip, false>::GetRHI();
// Disable Depth/Stencil test
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
FVertexDeclarationElementList Elements;
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = PipelineStateCache::GetOrCreateVertexDeclaration(Elements);
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = DrawVS.GetVertexShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleStrip;
// Set VS/PS shaders
if (hasHPlane)
{
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = DrawICtCpPS.GetPixelShader();
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
SetShaderParameters(RHICmdList, DrawICtCpPS, DrawICtCpPS.GetPixelShader(), *ictcp_params);
}
else
{
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = DrawYCbCrPS.GetPixelShader();
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0);
SetShaderParameters(RHICmdList, DrawYCbCrPS, DrawYCbCrPS.GetPixelShader(), *ycbcr_params);
}
SetShaderParameters(RHICmdList, DrawVS, DrawVS.GetVertexShader(), *vert_params);
RHICmdList.DrawPrimitive(0, 2, 1);
});
BinkGraphBuilder.Execute();
}
static void Set_draw_position(BINKTEXTURES * ptextures, F32 x0, F32 y0, F32 x1, F32 y1)
{
BINKTEXTURESRHI * textures = (BINKTEXTURESRHI*)ptextures;
textures->Ax = x0;
textures->Ay = y0;
textures->Bx = x1;
textures->By = y0;
textures->Cx = x0;
textures->Cy = y1;
}
static void Set_draw_corners(BINKTEXTURES * ptextures, F32 Ax, F32 Ay, F32 Bx, F32 By, F32 Cx, F32 Cy)
{
BINKTEXTURESRHI * textures = (BINKTEXTURESRHI*)ptextures;
textures->Ax = Ax;
textures->Ay = Ay;
textures->Bx = Bx;
textures->By = By;
textures->Cx = Cx;
textures->Cy = Cy;
}
static void Set_source_rect(BINKTEXTURES * ptextures, F32 u0, F32 v0, F32 u1, F32 v1)
{
BINKTEXTURESRHI * textures = (BINKTEXTURESRHI*)ptextures;
textures->u0 = u0;
textures->v0 = v0;
textures->u1 = u1;
textures->v1 = v1;
}
static void Set_alpha_settings(BINKTEXTURES * ptextures, F32 alpha_value, S32 draw_type)
{
BINKTEXTURESRHI * textures = (BINKTEXTURESRHI*)ptextures;
textures->alpha = alpha_value;
textures->draw_type = draw_type & 0x0FFFFFFF;
textures->draw_flags = draw_type & 0xF0000000;
}
static void Set_hdr_settings(BINKTEXTURES * ptextures, S32 tonemap, F32 exposure, S32 out_nits)
{
BINKTEXTURESRHI * textures = (BINKTEXTURESRHI*)ptextures;
textures->tonemap = tonemap;
textures->exposure = exposure;
textures->out_luma = ((F32)out_nits) / 80.f;
}