196 lines
4.9 KiB
C++
196 lines
4.9 KiB
C++
/***
|
|
|
|
Olive - Non-Linear Video Editor
|
|
Copyright (C) 2019 Olive Team
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
#include "openglcontext.h"
|
|
|
|
#include <QDebug>
|
|
|
|
OLIVE_NAMESPACE_ENTER
|
|
|
|
OpenGLContext::OpenGLContext(QObject* parent) :
|
|
RenderContext(parent)
|
|
{
|
|
}
|
|
|
|
OpenGLContext::~OpenGLContext()
|
|
{
|
|
}
|
|
|
|
bool OpenGLContext::Init()
|
|
{
|
|
surface_.create();
|
|
|
|
context_ = new QOpenGLContext();
|
|
if (!context_->create()) {
|
|
qCritical() << "Failed to create OpenGL context";
|
|
return false;
|
|
}
|
|
|
|
context_->moveToThread(this->thread());
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpenGLContext::PostInit()
|
|
{
|
|
// Make context current on that surface
|
|
if (!context_->makeCurrent(&surface_)) {
|
|
qCritical() << "Failed to makeCurrent() on offscreen surface in thread" << thread();
|
|
return;
|
|
}
|
|
|
|
// Store OpenGL functions instance
|
|
functions_ = context_->functions();
|
|
functions_->glBlendFunc(GL_ONE, GL_ZERO);
|
|
}
|
|
|
|
void OpenGLContext::Destroy()
|
|
{
|
|
delete context_;
|
|
surface_.destroy();
|
|
}
|
|
|
|
QVariant OpenGLContext::CreateTexture(const VideoParams &p, void *data, int linesize)
|
|
{
|
|
GLuint texture;
|
|
functions_->glGenTextures(1, &texture);
|
|
texture_params_.insert(texture, p);
|
|
|
|
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
|
|
|
functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(p.format()),
|
|
p.width(), p.height(), 0, GetPixelFormat(p.format()),
|
|
GetPixelType(p.format()), data);
|
|
|
|
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
|
|
return texture;
|
|
}
|
|
|
|
void OpenGLContext::DestroyTexture(QVariant texture)
|
|
{
|
|
GLuint t = texture.value<GLuint>();
|
|
functions_->glDeleteTextures(1, &t);
|
|
texture_params_.remove(t);
|
|
}
|
|
|
|
void OpenGLContext::UploadToTexture(QVariant texture, void *data, int linesize)
|
|
{
|
|
GLuint t = texture.value<GLuint>();
|
|
const VideoParams& p = texture_params_.value(t);
|
|
|
|
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
|
|
|
functions_->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
|
|
p.effective_width(), p.effective_height(),
|
|
GetPixelFormat(p.format()), GetPixelType(p.format()),
|
|
data);
|
|
|
|
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
}
|
|
|
|
void OpenGLContext::DownloadFromTexture(QVariant texture, void *data, int linesize)
|
|
{
|
|
GLuint t = texture.value<GLuint>();
|
|
const VideoParams& p = texture_params_.value(t);
|
|
|
|
functions_->glPixelStorei(GL_PACK_ROW_LENGTH, linesize);
|
|
|
|
functions_->glReadPixels(0,
|
|
0,
|
|
p.width(),
|
|
p.height(),
|
|
GetPixelFormat(p.format()),
|
|
GetPixelType(p.format()),
|
|
data);
|
|
|
|
functions_->glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
|
}
|
|
|
|
VideoParams OpenGLContext::GetParamsFromTexture(QVariant texture)
|
|
{
|
|
GLuint t = texture.value<GLuint>();
|
|
|
|
return texture_params_.value(t);
|
|
}
|
|
|
|
GLint OpenGLContext::GetInternalFormat(PixelFormat::Format format)
|
|
{
|
|
switch (format) {
|
|
case PixelFormat::PIX_FMT_RGB8:
|
|
return GL_RGB8;
|
|
case PixelFormat::PIX_FMT_RGBA8:
|
|
return GL_RGBA8;
|
|
case PixelFormat::PIX_FMT_RGB16U:
|
|
return GL_RGB16;
|
|
case PixelFormat::PIX_FMT_RGBA16U:
|
|
return GL_RGBA16;
|
|
case PixelFormat::PIX_FMT_RGB16F:
|
|
return GL_RGB16F;
|
|
case PixelFormat::PIX_FMT_RGBA16F:
|
|
return GL_RGBA16F;
|
|
case PixelFormat::PIX_FMT_RGB32F:
|
|
return GL_RGB32F;
|
|
case PixelFormat::PIX_FMT_RGBA32F:
|
|
return GL_RGBA32F;
|
|
|
|
case PixelFormat::PIX_FMT_INVALID:
|
|
case PixelFormat::PIX_FMT_COUNT:
|
|
break;
|
|
}
|
|
|
|
return GL_INVALID_VALUE;
|
|
}
|
|
|
|
GLenum OpenGLContext::GetPixelFormat(PixelFormat::Format format)
|
|
{
|
|
if (PixelFormat::FormatHasAlphaChannel(format)) {
|
|
return GL_RGBA;
|
|
} else {
|
|
return GL_RGB;
|
|
}
|
|
}
|
|
|
|
GLenum OpenGLContext::GetPixelType(PixelFormat::Format format)
|
|
{
|
|
switch (format) {
|
|
case PixelFormat::PIX_FMT_RGB8:
|
|
case PixelFormat::PIX_FMT_RGBA8:
|
|
return GL_UNSIGNED_BYTE;
|
|
case PixelFormat::PIX_FMT_RGB16U:
|
|
case PixelFormat::PIX_FMT_RGBA16U:
|
|
return GL_UNSIGNED_SHORT;
|
|
case PixelFormat::PIX_FMT_RGB16F:
|
|
case PixelFormat::PIX_FMT_RGBA16F:
|
|
return GL_HALF_FLOAT;
|
|
case PixelFormat::PIX_FMT_RGB32F:
|
|
case PixelFormat::PIX_FMT_RGBA32F:
|
|
return GL_FLOAT;
|
|
|
|
case PixelFormat::PIX_FMT_INVALID:
|
|
case PixelFormat::PIX_FMT_COUNT:
|
|
break;
|
|
}
|
|
|
|
return GL_INVALID_VALUE;
|
|
}
|
|
|
|
OLIVE_NAMESPACE_EXIT
|