finished upgrade to ocio v2
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
# 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/>.
|
||||
|
||||
add_subdirectory(opengl)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/backend/renderer.cpp
|
||||
render/backend/renderer.h
|
||||
render/backend/rendererthreadwrapper.cpp
|
||||
render/backend/rendererthreadwrapper.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -1,22 +0,0 @@
|
||||
# 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/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/backend/opengl/openglrenderer.cpp
|
||||
render/backend/opengl/openglrenderer.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -1,573 +0,0 @@
|
||||
/***
|
||||
|
||||
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 "openglrenderer.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFloat16>
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
const QVector<GLfloat> blit_vertices = {
|
||||
-1.0f, -1.0f, 0.0f,
|
||||
1.0f, -1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f,
|
||||
|
||||
-1.0f, -1.0f, 0.0f,
|
||||
-1.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f
|
||||
};
|
||||
|
||||
const QVector<GLfloat> blit_texcoords = {
|
||||
0.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
1.0f, 1.0f,
|
||||
|
||||
0.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
1.0f, 1.0f
|
||||
};
|
||||
|
||||
OpenGLRenderer::OpenGLRenderer(QObject* parent) :
|
||||
Renderer(parent),
|
||||
context_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
OpenGLRenderer::~OpenGLRenderer()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Init(QOpenGLContext *existing_ctx)
|
||||
{
|
||||
if (context_) {
|
||||
qCritical() << "Can't initialize already initialized OpenGLRenderer";
|
||||
return;
|
||||
}
|
||||
|
||||
context_ = existing_ctx;
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::Init()
|
||||
{
|
||||
if (context_) {
|
||||
qCritical() << "Can't initialize already initialized OpenGLRenderer";
|
||||
return false;
|
||||
}
|
||||
|
||||
surface_.create();
|
||||
|
||||
context_ = new QOpenGLContext(this);
|
||||
if (!context_->create()) {
|
||||
qCritical() << "Failed to create OpenGL context";
|
||||
return false;
|
||||
}
|
||||
|
||||
context_->moveToThread(this->thread());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PostInit()
|
||||
{
|
||||
// Make context current on that surface
|
||||
if (context_->parent() == this && !context_->makeCurrent(&surface_)) {
|
||||
qCritical() << "Failed to makeCurrent() on offscreen surface in thread" << thread();
|
||||
return;
|
||||
}
|
||||
|
||||
functions_ = context_->functions();
|
||||
|
||||
// Store OpenGL functions instance
|
||||
functions_->glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
// Set up framebuffer used for various things
|
||||
functions_->glGenFramebuffers(1, &framebuffer_);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Destroy()
|
||||
{
|
||||
if (context_) {
|
||||
// Delete framebuffer
|
||||
functions_->glDeleteFramebuffers(1, &framebuffer_);
|
||||
|
||||
// Delete context if it belongs to us
|
||||
if (context_->parent() == this) {
|
||||
delete context_;
|
||||
}
|
||||
context_ = nullptr;
|
||||
|
||||
// Destroy surface if we created it
|
||||
if (surface_.isValid()) {
|
||||
surface_.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::ClearDestination(double r, double g, double b, double a)
|
||||
{
|
||||
functions_->glClearColor(r, g, b, a);
|
||||
functions_->glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::AttachTextureAsDestination(Renderer::Texture* texture)
|
||||
{
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
|
||||
functions_->glFramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D,
|
||||
texture->id().value<GLuint>(),
|
||||
0);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DetachTextureAsDestination()
|
||||
{
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
QVariant OpenGLRenderer::CreateNativeTexture(VideoParams p, void *data, int linesize)
|
||||
{
|
||||
GLuint texture;
|
||||
functions_->glGenTextures(1, &texture);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
||||
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(p.format()),
|
||||
p.effective_width(), p.effective_height(), 0, GL_RGBA,
|
||||
GetPixelType(p.format()), data);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyNativeTexture(QVariant texture)
|
||||
{
|
||||
GLuint t = texture.value<GLuint>();
|
||||
functions_->glDeleteTextures(1, &t);
|
||||
}
|
||||
|
||||
QVariant OpenGLRenderer::CreateNativeShader(ShaderCode code)
|
||||
{
|
||||
QOpenGLShaderProgram* program = new QOpenGLShaderProgram(context_);
|
||||
|
||||
if (!program->addShaderFromSourceCode(QOpenGLShader::Vertex, code.vert_code())) {
|
||||
qCritical() << "Failed to add vertex code to shader";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!program->addShaderFromSourceCode(QOpenGLShader::Fragment, code.frag_code())) {
|
||||
qCritical() << "Failed to add fragment code to shader";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!program->link()) {
|
||||
qCritical() << "Failed to link shader";
|
||||
goto error;
|
||||
}
|
||||
|
||||
return Node::PtrToValue(program);
|
||||
|
||||
error:
|
||||
delete program;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyNativeShader(QVariant shader)
|
||||
{
|
||||
delete Node::ValueToPtr<QOpenGLShaderProgram>(shader);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::UploadToTexture(Texture *texture, void *data, int linesize)
|
||||
{
|
||||
GLuint t = texture->id().value<GLuint>();
|
||||
const VideoParams& p = texture->params();
|
||||
|
||||
// Store currently bound texture so it can be restored later
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, t);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
||||
|
||||
functions_->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
|
||||
p.effective_width(), p.effective_height(),
|
||||
GL_RGBA, GetPixelType(p.format()),
|
||||
data);
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DownloadFromTexture(Texture* texture, void *data, int linesize)
|
||||
{
|
||||
const VideoParams& p = texture->params();
|
||||
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex);
|
||||
|
||||
AttachTextureAsDestination(texture);
|
||||
|
||||
functions_->glPixelStorei(GL_PACK_ROW_LENGTH, linesize);
|
||||
|
||||
functions_->glReadPixels(0,
|
||||
0,
|
||||
p.width(),
|
||||
p.height(),
|
||||
GL_RGBA,
|
||||
GetPixelType(p.format()),
|
||||
data);
|
||||
|
||||
functions_->glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
|
||||
DetachTextureAsDestination();
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Renderer::Texture *destination, VideoParams destination_params)
|
||||
{
|
||||
// If this node is iterative, we'll pick up which input here
|
||||
GLuint iterative_input = 0;
|
||||
QList<GLuint> textures_to_bind;
|
||||
bool input_textures_have_alpha = false;
|
||||
|
||||
QOpenGLShaderProgram* shader = Node::ValueToPtr<QOpenGLShaderProgram>(s);
|
||||
|
||||
shader->bind();
|
||||
|
||||
NodeValueMap::const_iterator it;
|
||||
for (it=job.GetValues().constBegin(); it!=job.GetValues().constEnd(); it++) {
|
||||
// See if the shader has takes this parameter as an input
|
||||
int variable_location = shader->uniformLocation(it.key());
|
||||
|
||||
if (variable_location == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This variable is used in the shader, let's set it
|
||||
const ShaderValue& value = it.value();
|
||||
|
||||
if (value.array) {
|
||||
qWarning() << "FIXME: Array support is currently a stub";
|
||||
}
|
||||
|
||||
switch (value.type) {
|
||||
case NodeInput::kInt:
|
||||
// kInt technically specifies a LongLong, but OpenGL doesn't support those. This may lead to
|
||||
// over/underflows if the number is large enough, but the likelihood of that is quite low.
|
||||
shader->setUniformValue(variable_location, value.data.toInt());
|
||||
break;
|
||||
case NodeInput::kFloat:
|
||||
// kFloat technically specifies a double but as above, OpenGL doesn't support those.
|
||||
shader->setUniformValue(variable_location, value.data.toFloat());
|
||||
break;
|
||||
case NodeInput::kVec2:
|
||||
shader->setUniformValue(variable_location, value.data.value<QVector2D>());
|
||||
break;
|
||||
case NodeInput::kVec3:
|
||||
shader->setUniformValue(variable_location, value.data.value<QVector3D>());
|
||||
break;
|
||||
case NodeInput::kVec4:
|
||||
shader->setUniformValue(variable_location, value.data.value<QVector4D>());
|
||||
break;
|
||||
case NodeInput::kMatrix:
|
||||
shader->setUniformValue(variable_location, value.data.value<QMatrix4x4>());
|
||||
break;
|
||||
case NodeInput::kCombo:
|
||||
shader->setUniformValue(variable_location, value.data.value<int>());
|
||||
break;
|
||||
case NodeInput::kColor:
|
||||
{
|
||||
Color color = value.data.value<Color>();
|
||||
shader->setUniformValue(variable_location,
|
||||
color.red(), color.green(), color.blue(), color.alpha());
|
||||
break;
|
||||
}
|
||||
case NodeInput::kBoolean:
|
||||
shader->setUniformValue(variable_location, value.data.toBool());
|
||||
break;
|
||||
case NodeInput::kBuffer:
|
||||
case NodeInput::kTexture:
|
||||
{
|
||||
TexturePtr texture = value.data.value<TexturePtr>();
|
||||
|
||||
// Set value to bound texture
|
||||
shader->setUniformValue(variable_location, textures_to_bind.size());
|
||||
|
||||
// If this texture binding is the iterative input, set it here
|
||||
if (it.key() == job.GetIterativeInput()) {
|
||||
iterative_input = textures_to_bind.size();
|
||||
}
|
||||
|
||||
GLuint tex_id = texture ? texture->id().value<GLuint>() : 0;
|
||||
textures_to_bind.append(tex_id);
|
||||
|
||||
if (texture && texture->has_meaningful_alpha()) {
|
||||
input_textures_have_alpha = true;
|
||||
}
|
||||
|
||||
// Set enable flag if shader wants it
|
||||
int enable_param_location = shader->uniformLocation(QStringLiteral("%1_enabled").arg(it.key()));
|
||||
if (enable_param_location > -1) {
|
||||
shader->setUniformValue(enable_param_location,
|
||||
tex_id > 0);
|
||||
}
|
||||
|
||||
if (tex_id > 0) {
|
||||
// Set texture resolution if shader wants it
|
||||
int res_param_location = shader->uniformLocation(QStringLiteral("%1_resolution").arg(it.key()));
|
||||
if (res_param_location > -1) {
|
||||
int adjusted_width = texture->width() * texture->divider();
|
||||
|
||||
// Adjust virtual width by pixel aspect if necessary
|
||||
if (texture->params().pixel_aspect_ratio() != 1
|
||||
|| destination_params.pixel_aspect_ratio() != 1) {
|
||||
double relative_pixel_aspect = texture->params().pixel_aspect_ratio().toDouble() / destination_params.pixel_aspect_ratio().toDouble();
|
||||
|
||||
adjusted_width = qRound(static_cast<double>(adjusted_width) * relative_pixel_aspect);
|
||||
}
|
||||
|
||||
shader->setUniformValue(res_param_location,
|
||||
adjusted_width,
|
||||
static_cast<GLfloat>(texture->height() * texture->divider()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeInput::kSamples:
|
||||
case NodeInput::kText:
|
||||
case NodeInput::kRational:
|
||||
case NodeInput::kFont:
|
||||
case NodeInput::kFile:
|
||||
case NodeInput::kDecimal:
|
||||
case NodeInput::kNumber:
|
||||
case NodeInput::kString:
|
||||
case NodeInput::kVector:
|
||||
case NodeInput::kShaderJob:
|
||||
case NodeInput::kSampleJob:
|
||||
case NodeInput::kGenerateJob:
|
||||
case NodeInput::kFootage:
|
||||
case NodeInput::kNone:
|
||||
case NodeInput::kAny:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bind all textures
|
||||
for (int i=0; i<textures_to_bind.size(); i++) {
|
||||
functions_->glActiveTexture(GL_TEXTURE0 + i);
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, textures_to_bind.at(i));
|
||||
PrepareInputTexture(job.GetBilinearFiltering());
|
||||
}
|
||||
|
||||
// Set ove_resolution to the destination to the "logical" resolution of the destination
|
||||
shader->setUniformValue("ove_resolution",
|
||||
static_cast<GLfloat>(destination_params.width()),
|
||||
static_cast<GLfloat>(destination_params.height()));
|
||||
|
||||
// Set matrix to identity
|
||||
shader->setUniformValue("ove_mvpmat", job.GetMatrix());
|
||||
|
||||
// Set the viewport to the "physical" resolution of the destination
|
||||
functions_->glViewport(0, 0,
|
||||
destination_params.effective_width(),
|
||||
destination_params.effective_height());
|
||||
|
||||
// Bind vertex array object
|
||||
QOpenGLVertexArrayObject vao_;
|
||||
vao_.create();
|
||||
vao_.bind();
|
||||
|
||||
// Set buffers
|
||||
QOpenGLBuffer vert_vbo_;
|
||||
vert_vbo_.create();
|
||||
vert_vbo_.bind();
|
||||
vert_vbo_.allocate(blit_vertices.constData(), blit_vertices.size() * sizeof(GLfloat));
|
||||
vert_vbo_.release();
|
||||
|
||||
QOpenGLBuffer frag_vbo_;
|
||||
frag_vbo_.create();
|
||||
frag_vbo_.bind();
|
||||
frag_vbo_.allocate(blit_texcoords.constData(), blit_texcoords.size() * sizeof(GLfloat));
|
||||
frag_vbo_.release();
|
||||
|
||||
int vertex_location = shader->attributeLocation("a_position");
|
||||
vert_vbo_.bind();
|
||||
functions_->glEnableVertexAttribArray(vertex_location);
|
||||
functions_->glVertexAttribPointer(vertex_location, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
vert_vbo_.release();
|
||||
|
||||
int tex_location = shader->attributeLocation("a_texcoord");
|
||||
frag_vbo_.bind();
|
||||
functions_->glEnableVertexAttribArray(tex_location);
|
||||
functions_->glVertexAttribPointer(tex_location, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
frag_vbo_.release();
|
||||
|
||||
// Some shaders optimize through multiple iterations which requires ping-ponging textures
|
||||
// - If there are only two iterations, we can just create one backend texture and then the
|
||||
// destination can be the second
|
||||
// - If there are more than two iterations, we need to ping pong back and forth between two
|
||||
// textures. We can still use the destination as the last iteration, but we'll need textures
|
||||
// for the iterative process.
|
||||
int real_iteration_count;
|
||||
if (job.GetIterationCount() > 1 && !job.GetIterativeInput().isEmpty()) {
|
||||
real_iteration_count = job.GetIterationCount();
|
||||
} else {
|
||||
real_iteration_count = 1;
|
||||
}
|
||||
|
||||
TexturePtr output_tex, input_tex;
|
||||
if (real_iteration_count > 1) {
|
||||
// Create one texture to bounce off
|
||||
output_tex = CreateTexture(destination_params);
|
||||
|
||||
if (real_iteration_count > 2) {
|
||||
// Create a second texture bounce off
|
||||
input_tex = CreateTexture(destination_params);
|
||||
}
|
||||
}
|
||||
|
||||
for (int iteration=0; iteration<real_iteration_count; iteration++) {
|
||||
// Set iteration number
|
||||
shader->setUniformValue("ove_iteration", iteration);
|
||||
|
||||
// Replace iterative input
|
||||
if (iteration == real_iteration_count-1) {
|
||||
// This is the last iteration, draw to the destination
|
||||
if (destination) {
|
||||
// If we have a destination texture, draw to it
|
||||
AttachTextureAsDestination(destination);
|
||||
} else if (iteration > 0) {
|
||||
// Otherwise, if we were iterating before, detach texture now
|
||||
DetachTextureAsDestination();
|
||||
}
|
||||
} else {
|
||||
// Always draw to output_tex, which gets swapped with input_tex every iteration
|
||||
AttachTextureAsDestination(output_tex.get());
|
||||
}
|
||||
|
||||
if (iteration > 0) {
|
||||
// If this is not the first iteration, replace the iterative texture with the one we
|
||||
// last drew
|
||||
functions_->glActiveTexture(GL_TEXTURE0 + iterative_input);
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, input_tex->id().value<GLuint>());
|
||||
PrepareInputTexture(job.GetBilinearFiltering());
|
||||
}
|
||||
|
||||
// Swap so that the next iteration, the texture we draw now will be the input texture next
|
||||
std::swap(output_tex, input_tex);
|
||||
|
||||
// Blit this texture through this shader
|
||||
functions_->glDrawArrays(GL_TRIANGLES, 0, blit_vertices.size() / 3);
|
||||
}
|
||||
|
||||
if (destination) {
|
||||
// Reset framebuffer to default if we were drawing to a texture
|
||||
DetachTextureAsDestination();
|
||||
|
||||
// Set metadata for whether this texture has a meaningful alpha channel
|
||||
destination->set_has_meaningful_alpha((input_textures_have_alpha || job.GetAlphaChannelRequired()));
|
||||
}
|
||||
|
||||
// Release any textures we bound before
|
||||
for (int i=textures_to_bind.size()-1; i>=0; i--) {
|
||||
functions_->glActiveTexture(GL_TEXTURE0 + i);
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// Release shader
|
||||
shader->release();
|
||||
|
||||
// Release vertex array object
|
||||
frag_vbo_.destroy();
|
||||
vert_vbo_.destroy();
|
||||
vao_.release();
|
||||
vao_.destroy();
|
||||
}
|
||||
|
||||
GLint OpenGLRenderer::GetInternalFormat(PixelFormat::Format format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_RGBA8;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_RGBA16;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_RGBA16F;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_RGBA32F;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderer::GetPixelType(PixelFormat::Format format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_HALF_FLOAT;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_FLOAT;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PrepareInputTexture(bool bilinear)
|
||||
{
|
||||
if (bilinear) {
|
||||
// Use mipmapped bilinear
|
||||
functions_->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else {
|
||||
// Use nearest
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
functions_->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -1,95 +0,0 @@
|
||||
/***
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OPENGLCONTEXT_H
|
||||
#define OPENGLCONTEXT_H
|
||||
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLBuffer>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLShader>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "render/backend/renderer.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class OpenGLRenderer : public Renderer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
OpenGLRenderer(QObject* parent = nullptr);
|
||||
|
||||
virtual ~OpenGLRenderer() override;
|
||||
|
||||
void Init(QOpenGLContext* existing_ctx);
|
||||
|
||||
virtual bool Init() override;
|
||||
|
||||
public slots:
|
||||
virtual void PostInit() override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
|
||||
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
|
||||
|
||||
virtual QVariant CreateNativeTexture(OLIVE_NAMESPACE::VideoParams param, void* data = nullptr, int linesize = 0) override;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
|
||||
virtual QVariant CreateNativeShader(OLIVE_NAMESPACE::ShaderCode code) override;
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
|
||||
protected slots:
|
||||
virtual void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination,
|
||||
OLIVE_NAMESPACE::VideoParams destination_params) override;
|
||||
|
||||
private:
|
||||
static GLint GetInternalFormat(PixelFormat::Format format);
|
||||
|
||||
static GLenum GetPixelType(PixelFormat::Format format);
|
||||
|
||||
void AttachTextureAsDestination(OLIVE_NAMESPACE::Renderer::Texture* texture);
|
||||
|
||||
void DetachTextureAsDestination();
|
||||
|
||||
void PrepareInputTexture(bool bilinear);
|
||||
|
||||
QOpenGLContext* context_;
|
||||
|
||||
QOpenGLFunctions* functions_;
|
||||
|
||||
QOffscreenSurface surface_;
|
||||
|
||||
GLuint framebuffer_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // OPENGLCONTEXT_H
|
||||
@@ -1,113 +0,0 @@
|
||||
/***
|
||||
|
||||
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 "renderer.h"
|
||||
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/ocioutils.h"
|
||||
#include "render/colormanager.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
Renderer::Renderer(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Renderer::TexturePtr Renderer::CreateTexture(const VideoParams ¶m, void *data, int linesize)
|
||||
{
|
||||
QVariant v = CreateNativeTexture(param, data, linesize);
|
||||
|
||||
if (v.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<Texture>(this, v, param);
|
||||
}
|
||||
|
||||
// copied from source code to OCIODisplay
|
||||
/*const int OCIO_LUT3D_EDGE_SIZE = 64;
|
||||
|
||||
const int OCIO_LUT3D_PIXEL_COUNT = OCIO_LUT3D_EDGE_SIZE*OCIO_LUT3D_EDGE_SIZE*OCIO_LUT3D_EDGE_SIZE;
|
||||
const int OCIO_LUT3D_ENTRY_COUNT = 3 * OCIO_LUT3D_PIXEL_COUNT;
|
||||
const int OCIO_LUT3D_ENTRY_COUNT_WITH_ALPHA = 4 * OCIO_LUT3D_PIXEL_COUNT;
|
||||
const int OCIO_LUT2D_EDGE_SIZE = 512;*/
|
||||
|
||||
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, Texture *destination, bool flipped)
|
||||
{
|
||||
qDebug() << "BlitColorManaged is a partial stub";
|
||||
|
||||
QVariant shader = CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(":/shaders/default.frag"), FileFunctions::ReadFileAsString(":/shaders/default.vert")));
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(source), NodeParam::kTexture));
|
||||
|
||||
if (flipped) {
|
||||
QMatrix4x4 mat;
|
||||
mat.scale(1, -1, 1);
|
||||
job.SetMatrix(mat);
|
||||
}
|
||||
|
||||
BlitToTexture(shader, job, destination);
|
||||
|
||||
DestroyNativeShader(shader);
|
||||
}
|
||||
|
||||
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, VideoParams params, bool flipped)
|
||||
{
|
||||
qDebug() << "BlitColorManaged is a partial stub";
|
||||
|
||||
/*ColorContext color_ctx;
|
||||
|
||||
if (color_cache_.contains(color_processor->id())) {
|
||||
color_ctx = color_cache_.value(color_processor->id());
|
||||
} else {
|
||||
// Create shader description
|
||||
const char* ocio_func_name = "OCIODisplay";
|
||||
OCIO::GpuShaderDescRcPtr shader_desc = OCIO::GpuShaderDesc::CreateShaderDesc();
|
||||
shader_desc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
|
||||
shader_desc->setFunctionName(ocio_func_name);
|
||||
shader_desc->setResourcePrefix("ocio_");
|
||||
|
||||
// Generate shader
|
||||
color_processor->GetProcessor()->getDefaultGPUProcessor()->extractGpuShaderInfo(shader_desc);
|
||||
|
||||
qDebug() << "Shader:" << shader_desc->getShaderText();
|
||||
}*/
|
||||
|
||||
QVariant shader = CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(":/shaders/default.frag"), FileFunctions::ReadFileAsString(":/shaders/default.vert")));
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(source), NodeParam::kTexture));
|
||||
|
||||
if (flipped) {
|
||||
QMatrix4x4 mat;
|
||||
mat.scale(1, -1, 1);
|
||||
job.SetMatrix(mat);
|
||||
}
|
||||
|
||||
Blit(shader, job, params);
|
||||
|
||||
DestroyNativeShader(shader);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -1,180 +0,0 @@
|
||||
/***
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERCONTEXT_H
|
||||
#define RENDERCONTEXT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "common/timerange.h"
|
||||
#include "node/node.h"
|
||||
#include "render/colorprocessor.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class Renderer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Renderer(QObject* parent = nullptr);
|
||||
|
||||
virtual bool Init() = 0;
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param) :
|
||||
renderer_(renderer),
|
||||
params_(param),
|
||||
id_(native),
|
||||
meaningful_alpha_(true)
|
||||
{
|
||||
}
|
||||
|
||||
~Texture()
|
||||
{
|
||||
renderer_->DestroyNativeTexture(id_);
|
||||
}
|
||||
|
||||
QVariant id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
const VideoParams& params() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
void Upload(void* data, int linesize)
|
||||
{
|
||||
renderer_->UploadToTexture(this, data, linesize);
|
||||
}
|
||||
|
||||
int width() const
|
||||
{
|
||||
return params_.width();
|
||||
}
|
||||
|
||||
int height() const
|
||||
{
|
||||
return params_.height();
|
||||
}
|
||||
|
||||
PixelFormat::Format format() const
|
||||
{
|
||||
return params_.format();
|
||||
}
|
||||
|
||||
int divider() const
|
||||
{
|
||||
return params_.divider();
|
||||
}
|
||||
|
||||
const rational& pixel_aspect_ratio() const
|
||||
{
|
||||
return params_.pixel_aspect_ratio();
|
||||
}
|
||||
|
||||
bool has_meaningful_alpha() const
|
||||
{
|
||||
return meaningful_alpha_;
|
||||
}
|
||||
|
||||
void set_has_meaningful_alpha(bool e)
|
||||
{
|
||||
meaningful_alpha_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
Renderer* renderer_;
|
||||
|
||||
VideoParams params_;
|
||||
|
||||
QVariant id_;
|
||||
|
||||
bool meaningful_alpha_;
|
||||
|
||||
};
|
||||
|
||||
using TexturePtr = std::shared_ptr<Texture>;
|
||||
|
||||
TexturePtr CreateTexture(const VideoParams& param, void* data = nullptr, int linesize = 0);
|
||||
|
||||
void BlitToTexture(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination)
|
||||
{
|
||||
Blit(shader, job, destination, destination->params());
|
||||
}
|
||||
|
||||
void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::VideoParams params)
|
||||
{
|
||||
Blit(shader, job, nullptr, params);
|
||||
}
|
||||
|
||||
void BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, Texture* destination, bool flipped = false);
|
||||
void BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, VideoParams params, bool flipped = false);
|
||||
|
||||
public slots:
|
||||
virtual void PostInit() = 0;
|
||||
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) = 0;
|
||||
|
||||
virtual QVariant CreateNativeTexture(OLIVE_NAMESPACE::VideoParams param, void* data = nullptr, int linesize = 0) = 0;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) = 0;
|
||||
|
||||
virtual QVariant CreateNativeShader(OLIVE_NAMESPACE::ShaderCode code) = 0;
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) = 0;
|
||||
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) = 0;
|
||||
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) = 0;
|
||||
|
||||
protected slots:
|
||||
virtual void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination,
|
||||
OLIVE_NAMESPACE::VideoParams destination_params) = 0;
|
||||
|
||||
private:
|
||||
struct ColorContext {
|
||||
QVariant shader;
|
||||
TexturePtr lut;
|
||||
};
|
||||
|
||||
QHash<QString, ColorContext> color_cache_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::Renderer::TexturePtr);
|
||||
|
||||
#endif // RENDERCONTEXT_H
|
||||
@@ -1,142 +0,0 @@
|
||||
/***
|
||||
|
||||
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 "rendererthreadwrapper.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
RendererThreadWrapper::RendererThreadWrapper(Renderer *inner, QObject *parent) :
|
||||
Renderer(parent),
|
||||
inner_(inner),
|
||||
thread_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool RendererThreadWrapper::Init()
|
||||
{
|
||||
// Init context in main thread
|
||||
if (!inner_->Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create thread
|
||||
thread_ = new QThread(this);
|
||||
thread_->start(QThread::IdlePriority);
|
||||
|
||||
// Move context to thread
|
||||
inner_->moveToThread(thread_);
|
||||
|
||||
// Queue post-init in new thread
|
||||
QMetaObject::invokeMethod(inner_, "PostInit", Qt::BlockingQueuedConnection);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::PostInit()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::Destroy()
|
||||
{
|
||||
if (thread_) {
|
||||
QMetaObject::invokeMethod(inner_, "Destroy", Qt::BlockingQueuedConnection);
|
||||
inner_ = nullptr;
|
||||
|
||||
thread_->quit();
|
||||
thread_->wait();
|
||||
delete thread_;
|
||||
thread_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::ClearDestination(double r, double g, double b, double a)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "ClearDestination", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(double, r),
|
||||
Q_ARG(double, g),
|
||||
Q_ARG(double, b),
|
||||
Q_ARG(double, a));
|
||||
}
|
||||
|
||||
QVariant RendererThreadWrapper::CreateNativeTexture(VideoParams param, void *data, int linesize)
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
QMetaObject::invokeMethod(inner_, "CreateNativeTexture", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, v),
|
||||
OLIVE_NS_ARG(VideoParams, param),
|
||||
Q_ARG(void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::DestroyNativeTexture(QVariant texture)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "DestroyNativeTexture", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QVariant, texture));
|
||||
}
|
||||
|
||||
QVariant RendererThreadWrapper::CreateNativeShader(ShaderCode code)
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
QMetaObject::invokeMethod(inner_, "CreateNativeShader", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, v),
|
||||
OLIVE_NS_ARG(ShaderCode, code));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::DestroyNativeShader(QVariant shader)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "DestroyNativeShader", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QVariant, shader));
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::UploadToTexture(Renderer::Texture *texture, void *data, int linesize)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "UploadToTexture", Qt::BlockingQueuedConnection,
|
||||
OLIVE_NS_ARG(Renderer::Texture*, texture),
|
||||
Q_ARG(void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::DownloadFromTexture(Renderer::Texture *texture, void *data, int linesize)
|
||||
{
|
||||
QMetaObject::invokeMethod(inner_, "DownloadFromTexture", Qt::BlockingQueuedConnection,
|
||||
OLIVE_NS_ARG(Renderer::Texture*, texture),
|
||||
Q_ARG(void*, data),
|
||||
Q_ARG(int, linesize));
|
||||
}
|
||||
|
||||
void RendererThreadWrapper::Blit(QVariant shader, ShaderJob job, Renderer::Texture *destination, VideoParams destination_params)
|
||||
{
|
||||
Renderer::TexturePtr tex;
|
||||
|
||||
QMetaObject::invokeMethod(inner_, "Blit", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QVariant, shader),
|
||||
OLIVE_NS_ARG(ShaderJob, job),
|
||||
OLIVE_NS_ARG(Renderer::Texture*, destination),
|
||||
OLIVE_NS_ARG(VideoParams, destination_params));
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -1,77 +0,0 @@
|
||||
/***
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERCONTEXTTHREADWRAPPER_H
|
||||
#define RENDERCONTEXTTHREADWRAPPER_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class RendererThreadWrapper : public Renderer
|
||||
{
|
||||
public:
|
||||
RendererThreadWrapper(Renderer* inner, QObject* parent = nullptr);
|
||||
|
||||
virtual ~RendererThreadWrapper() override
|
||||
{
|
||||
Destroy();
|
||||
delete inner_;
|
||||
}
|
||||
|
||||
virtual bool Init() override;
|
||||
|
||||
public slots:
|
||||
virtual void PostInit() override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
|
||||
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
|
||||
|
||||
virtual QVariant CreateNativeTexture(OLIVE_NAMESPACE::VideoParams param, void* data = nullptr, int linesize = 0) override;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
|
||||
virtual QVariant CreateNativeShader(OLIVE_NAMESPACE::ShaderCode code) override;
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
|
||||
virtual void UploadToTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
|
||||
virtual void DownloadFromTexture(OLIVE_NAMESPACE::Renderer::Texture* texture, void* data, int linesize) override;
|
||||
|
||||
protected slots:
|
||||
virtual void Blit(QVariant shader,
|
||||
OLIVE_NAMESPACE::ShaderJob job,
|
||||
OLIVE_NAMESPACE::Renderer::Texture* destination,
|
||||
OLIVE_NAMESPACE::VideoParams destination_params) override;
|
||||
|
||||
private:
|
||||
Renderer* inner_;
|
||||
|
||||
QThread* thread_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // RENDERCONTEXTTHREADWRAPPER_H
|
||||
Reference in New Issue
Block a user