#include "gltexture.hpp" #include <nanogui/opengl.h> #include <loguru.hpp> #include <ftl/cuda_common.hpp> #include <cuda_gl_interop.h> #include <ftl/exception.hpp> using ftl::gui::GLTexture; GLTexture::GLTexture() { glid_ = std::numeric_limits<unsigned int>::max(); glbuf_ = std::numeric_limits<unsigned int>::max(); cuda_res_ = nullptr; width_ = 0; height_ = 0; changed_ = true; } GLTexture::~GLTexture() { //glDeleteTextures(1, &glid_); } void GLTexture::update(cv::Mat &m) { LOG(INFO) << "DEPRECATED"; if (m.rows == 0) return; if (glid_ == std::numeric_limits<unsigned int>::max()) { glGenTextures(1, &glid_); glBindTexture(GL_TEXTURE_2D, glid_); //cv::Mat m(cv::Size(100,100), CV_8UC3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m.cols, m.rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, m.data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { //glBindTexture(GL_TEXTURE_2D, glid_); // TODO Allow for other formats //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m.cols, m.rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, m.data); } auto err = glGetError(); if (err != 0) LOG(ERROR) << "OpenGL Texture error: " << err; } void GLTexture::make(int width, int height) { if (width != width_ || height != height_) { free(); } width_ = width; height_ = height; if (width == 0 || height == 0) { throw FTL_Error("Invalid texture size"); } if (glid_ == std::numeric_limits<unsigned int>::max()) { glGenTextures(1, &glid_); glBindTexture(GL_TEXTURE_2D, glid_); //cv::Mat m(cv::Size(100,100), CV_8UC3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //auto err = glGetError(); //if (err != 0) LOG(ERROR) << "OpenGL Texture error: " << err; glBindTexture(GL_TEXTURE_2D, 0); glGenBuffers(1, &glbuf_); // Make this the current UNPACK buffer (OpenGL is state-based) glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glbuf_); // Allocate data for the buffer. 4-channel 8-bit image glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_DYNAMIC_COPY); cudaSafeCall(cudaGraphicsGLRegisterBuffer(&cuda_res_, glbuf_, cudaGraphicsRegisterFlagsWriteDiscard)); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } } void GLTexture::free() { if (glid_ != std::numeric_limits<unsigned int>::max()) { glDeleteTextures(1, &glid_); glid_ = std::numeric_limits<unsigned int>::max(); } if (glbuf_ != std::numeric_limits<unsigned int>::max()) { cudaSafeCall(cudaGraphicsUnregisterResource( cuda_res_ )); cuda_res_ = nullptr; glDeleteBuffers(1, &glbuf_); glbuf_ = std::numeric_limits<unsigned int>::max(); } } cv::cuda::GpuMat GLTexture::map(cudaStream_t stream) { void *devptr; size_t size; cudaSafeCall(cudaGraphicsMapResources(1, &cuda_res_, stream)); cudaSafeCall(cudaGraphicsResourceGetMappedPointer(&devptr, &size, cuda_res_)); return cv::cuda::GpuMat(height_, width_, CV_8UC4, devptr); } void GLTexture::unmap(cudaStream_t stream) { cudaSafeCall(cudaGraphicsUnmapResources(1, &cuda_res_, stream)); changed_ = true; //glActiveTexture(GL_TEXTURE0); glBindBuffer( GL_PIXEL_UNPACK_BUFFER, glbuf_); // Select the appropriate texture glBindTexture( GL_TEXTURE_2D, glid_); // Make a texture from the buffer glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL); glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0); } unsigned int GLTexture::texture() const { if (glbuf_ < std::numeric_limits<unsigned int>::max()) { /*//glActiveTexture(GL_TEXTURE0); glBindBuffer( GL_PIXEL_UNPACK_BUFFER, glbuf_); // Select the appropriate texture glBindTexture( GL_TEXTURE_2D, glid_); // Make a texture from the buffer glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL); glBindBuffer( GL_PIXEL_UNPACK_BUFFER, 0);*/ return glid_; } else { return glid_; } }