179 lines
4.7 KiB
C++
179 lines
4.7 KiB
C++
#include "opengl_backend.h"
|
|
#include <logger.h>
|
|
|
|
bool OpenGLTextureBackend::InitializeGLAD()
|
|
{
|
|
gladLoaderLoadEGL(EGL_NO_DISPLAY);
|
|
int egl_version = gladLoadEGL(eglGetCurrentDisplay(), eglGetProcAddress);
|
|
if (egl_version == 0)
|
|
{
|
|
Logger::Log("OpenGLTextureBackend: Failed to load EGL");
|
|
return false;
|
|
}
|
|
|
|
int gl_version = gladLoaderLoadGLES2();
|
|
if (gl_version == 0)
|
|
{
|
|
Logger::Log("OpenGLTextureBackend: Failed to load GLES2");
|
|
return false;
|
|
}
|
|
|
|
Logger::Log("OpenGLTextureBackend: GLAD initialized successfully");
|
|
return true;
|
|
}
|
|
|
|
bool OpenGLTextureBackend::Create(AHardwareBuffer* buffer)
|
|
{
|
|
if (m_Created)
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
// Get buffer dimensions
|
|
AHardwareBuffer_Desc desc{};
|
|
AHardwareBuffer_describe(buffer, &desc);
|
|
m_Width = static_cast<GLint>(desc.width);
|
|
m_Height = static_cast<GLint>(desc.height);
|
|
|
|
// Create EGL image from hardware buffer
|
|
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer);
|
|
EGLImageKHR eglImage = eglCreateImageKHR(
|
|
eglGetCurrentDisplay(),
|
|
EGL_NO_CONTEXT,
|
|
EGL_NATIVE_BUFFER_ANDROID,
|
|
clientBuffer,
|
|
nullptr
|
|
);
|
|
|
|
if (eglImage == EGL_NO_IMAGE_KHR)
|
|
{
|
|
Logger::Log("OpenGLTextureBackend: Failed to create EGL image");
|
|
return false;
|
|
}
|
|
|
|
// Create source texture (external OES format from hardware buffer)
|
|
glGenTextures(1, &m_SourceTexture);
|
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, m_SourceTexture);
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
|
|
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
|
|
|
|
// Create source framebuffer
|
|
glGenFramebuffers(1, &m_SourceFramebuffer);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_SourceFramebuffer);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT0,
|
|
GL_TEXTURE_EXTERNAL_OES,
|
|
m_SourceTexture,
|
|
0
|
|
);
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
Logger::Log("OpenGLTextureBackend: Source framebuffer incomplete");
|
|
Destroy();
|
|
return false;
|
|
}
|
|
|
|
// Create destination texture (standard 2D texture for Unity)
|
|
glGenTextures(1, &m_DestTexture);
|
|
glBindTexture(GL_TEXTURE_2D, m_DestTexture);
|
|
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_RGB,
|
|
m_Width,
|
|
m_Height,
|
|
0,
|
|
GL_RGB,
|
|
GL_UNSIGNED_BYTE,
|
|
nullptr
|
|
);
|
|
|
|
// Create destination framebuffer
|
|
glGenFramebuffers(1, &m_DestFramebuffer);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_DestFramebuffer);
|
|
glFramebufferTexture2D(
|
|
GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT0,
|
|
GL_TEXTURE_2D,
|
|
m_DestTexture,
|
|
0
|
|
);
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
Logger::Log("OpenGLTextureBackend: Dest framebuffer incomplete");
|
|
Destroy();
|
|
return false;
|
|
}
|
|
|
|
m_Created = true;
|
|
|
|
// Initial blit
|
|
Blit();
|
|
|
|
Logger::Log("OpenGLTextureBackend: Created successfully");
|
|
return true;
|
|
}
|
|
|
|
void OpenGLTextureBackend::Update()
|
|
{
|
|
if (m_Created)
|
|
{
|
|
Blit();
|
|
}
|
|
}
|
|
|
|
void OpenGLTextureBackend::Blit()
|
|
{
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_SourceFramebuffer);
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_DestFramebuffer);
|
|
glBlitFramebuffer(
|
|
0, 0, m_Width, m_Height,
|
|
0, 0, m_Width, m_Height,
|
|
GL_COLOR_BUFFER_BIT,
|
|
GL_NEAREST
|
|
);
|
|
}
|
|
|
|
void OpenGLTextureBackend::Destroy()
|
|
{
|
|
if (m_DestFramebuffer)
|
|
{
|
|
glDeleteFramebuffers(1, &m_DestFramebuffer);
|
|
m_DestFramebuffer = 0;
|
|
}
|
|
if (m_SourceFramebuffer)
|
|
{
|
|
glDeleteFramebuffers(1, &m_SourceFramebuffer);
|
|
m_SourceFramebuffer = 0;
|
|
}
|
|
if (m_DestTexture)
|
|
{
|
|
glDeleteTextures(1, &m_DestTexture);
|
|
m_DestTexture = 0;
|
|
}
|
|
if (m_SourceTexture)
|
|
{
|
|
glDeleteTextures(1, &m_SourceTexture);
|
|
m_SourceTexture = 0;
|
|
}
|
|
m_Width = 0;
|
|
m_Height = 0;
|
|
m_Created = false;
|
|
}
|
|
|
|
void* OpenGLTextureBackend::GetNativeTexturePtr()
|
|
{
|
|
return reinterpret_cast<void*>(static_cast<uintptr_t>(m_DestTexture));
|
|
}
|