Files
video-shader-toys/apps/RenderCadenceCompositor/render/InputFrameTexture.cpp
Aiden ce28904891
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 3m2s
CI / Windows Release Package (push) Has been skipped
input testing
2026-05-12 20:06:23 +10:00

109 lines
2.8 KiB
C++

#include "InputFrameTexture.h"
#include <chrono>
InputFrameTexture::~InputFrameTexture()
{
ShutdownGl();
}
GLuint InputFrameTexture::PollAndUpload(InputFrameMailbox* mailbox)
{
if (mailbox == nullptr)
return mTexture;
InputFrame frame;
if (!mailbox->TryAcquireLatest(frame))
{
++mUploadMisses;
mLastUploadMilliseconds = 0.0;
return mTexture;
}
if (frame.bytes != nullptr && frame.pixelFormat == VideoIOPixelFormat::Bgra8 && EnsureTexture(frame))
{
mLastFrameFormatSupported = true;
const auto uploadStart = std::chrono::steady_clock::now();
UploadBgra8FrameFlippedVertically(frame);
const auto uploadEnd = std::chrono::steady_clock::now();
mLastUploadMilliseconds = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(uploadEnd - uploadStart).count();
++mUploadedFrames;
}
else
{
mLastFrameFormatSupported = frame.pixelFormat == VideoIOPixelFormat::Bgra8;
mLastUploadMilliseconds = 0.0;
}
mailbox->Release(frame);
return mTexture;
}
void InputFrameTexture::ShutdownGl()
{
if (mTexture != 0)
glDeleteTextures(1, &mTexture);
mTexture = 0;
mWidth = 0;
mHeight = 0;
}
bool InputFrameTexture::EnsureTexture(const InputFrame& frame)
{
if (frame.width == 0 || frame.height == 0)
return false;
if (mTexture != 0 && mWidth == frame.width && mHeight == frame.height)
return true;
ShutdownGl();
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA8,
static_cast<GLsizei>(frame.width),
static_cast<GLsizei>(frame.height),
0,
GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV,
nullptr);
glBindTexture(GL_TEXTURE_2D, 0);
mWidth = frame.width;
mHeight = frame.height;
return mTexture != 0;
}
void InputFrameTexture::UploadBgra8FrameFlippedVertically(const InputFrame& frame)
{
glBindTexture(GL_TEXTURE_2D, mTexture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, frame.rowBytes > 0 ? static_cast<GLint>(frame.rowBytes / 4) : 0);
const unsigned char* sourceBytes = static_cast<const unsigned char*>(frame.bytes);
for (unsigned destinationY = 0; destinationY < frame.height; ++destinationY)
{
const unsigned sourceY = frame.height - 1u - destinationY;
const unsigned char* sourceRow = sourceBytes + static_cast<std::size_t>(sourceY) * static_cast<std::size_t>(frame.rowBytes);
glTexSubImage2D(
GL_TEXTURE_2D,
0,
0,
static_cast<GLint>(destinationY),
static_cast<GLsizei>(frame.width),
1,
GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV,
sourceRow);
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}