// 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] = RHICmdList.CreateTexture(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] = RHICmdList.CreateTexture(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] = RHICmdList.CreateTexture(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] = RHICmdList.CreateTexture(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] = RHICmdList.CreateTexture(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(); 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::GetRHI(); consts->samp1 = TStaticSamplerState::GetRHI(); consts->samp2 = TStaticSamplerState::GetRHI(); consts->samp3 = TStaticSamplerState::GetRHI(); consts->samp4 = TStaticSamplerState::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(); vert_params->BinkParameters = *consts; FBinkDrawICtCpPS::FParameters* ictcp_params = BinkGraphBuilder.AllocParameters(); ictcp_params->BinkParameters = *consts; FBinkDrawYCbCrPS::FParameters* ycbcr_params = BinkGraphBuilder.AllocParameters(); ycbcr_params->BinkParameters = *consts; auto* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel); TShaderMapRef DrawVS(ShaderMap); FBinkDrawICtCpPS::FPermutationDomain ictcp_pv; ictcp_pv.Set(!!hasAPlane); ictcp_pv.Set(textures->tonemap == 1); ictcp_pv.Set(textures->tonemap == 2); TShaderMapRef DrawICtCpPS(ShaderMap, ictcp_pv); FBinkDrawYCbCrPS::FPermutationDomain ycbcr_pv; ycbcr_pv.Set(!!hasAPlane); ycbcr_pv.Set(!!(textures->draw_flags & 0x80000000)); TShaderMapRef 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::GetRHI(); } else { // normal alpha GraphicsPSOInit.BlendState = TStaticBlendState::GetRHI(); } // Disable backface culling GraphicsPSOInit.RasterizerState = TStaticRasterizerState::GetRHI(); // Disable Depth/Stencil test GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::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; }