two step process and configurable colorspaces

This commit is contained in:
itsmattkc
2019-03-20 01:42:40 +11:00
parent 0a5c3fe36e
commit 7d337e6de2
17 changed files with 559 additions and 244 deletions
+149 -25
View File
@@ -31,11 +31,6 @@ extern "C" {
#include <QOpenGLVertexArrayObject>
#include <QDebug>
#ifndef NO_OCIO
#include <OpenColorIO/OpenColorIO.h>
namespace OCIO = OCIO_NAMESPACE;
#endif
#include "timeline/clip.h"
#include "timeline/sequence.h"
#include "project/media.h"
@@ -80,6 +75,14 @@ GLfloat olive::rendering::flipped_blit_texcoords[] = {
1.0, 0.0
};
#ifndef NO_OCIO
// copied from source code to OCIODisplay
const int OCIO_LUT3D_EDGE_SIZE = 32;
// copied from source code to OCIODisplay, expanded from 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE
const int OCIO_NUM_3D_ENTRIES = 98304;
#endif
void olive::rendering::Blit(QOpenGLShaderProgram* pipeline, bool flipped, QMatrix4x4 matrix) {
QOpenGLVertexArrayObject m_vao;
@@ -237,6 +240,7 @@ GLuint draw_clip(QOpenGLContext* ctx,
const FramebufferObject& fbo,
GLuint texture,
bool clear) {
fbo.BindBuffer();
if (clear) {
@@ -252,6 +256,7 @@ GLuint draw_clip(QOpenGLContext* ctx,
fbo.ReleaseBuffer();
return fbo.texture();
}
void process_effect(QOpenGLContext* ctx,
@@ -305,7 +310,7 @@ void process_effect(QOpenGLContext* ctx,
}
GLuint compose_sequence(ComposeSequenceParams &params) {
GLuint final_fbo = params.main_buffer;
GLuint final_fbo = params.video ? params.main_buffer->buffer() : 0;
Sequence* s = params.seq;
long playhead = s->playhead;
@@ -511,7 +516,7 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
} else if (c->media()->get_type() == MEDIA_TYPE_FOOTAGE) {
if (!c->media()->to_footage()->alpha_is_premultiplied) {
if (!c->media()->to_footage()->alpha_is_associated) {
// alpha is not premultiplied, we'll need to multiply it for the rest of the pipeline
params.ctx->functions()->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ZERO);
@@ -525,27 +530,52 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
}
#ifndef NO_OCIO
// convert to linear colorspace
if (olive::CurrentConfig.enable_color_management && params.ocio_shader != nullptr)
// Convert frame from source to linear colorspace
if (olive::CurrentConfig.enable_color_management)
{
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE2);
params.ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, params.ocio_lut_texture);
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE0);
if (c->ocio_shader == nullptr) {
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
params.ocio_shader->bind();
QString input_cs = OCIO::ROLE_SCENE_LINEAR;
params.ocio_shader->setUniformValue("tex2", 2);
if (c->media() != nullptr && c->media()->get_type() == MEDIA_TYPE_FOOTAGE) {
textureID = draw_clip(params.ctx, params.ocio_shader, c->fbo.at(fbo_switcher), textureID, true);
if (!c->media()->to_footage()->colorspace.isEmpty()) {
params.ocio_shader->release();
input_cs = c->media()->to_footage()->colorspace;
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE2);
params.ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, 0);
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE0);
} else {
fbo_switcher = !fbo_switcher;
// If this is a footage clip, try to guess the color space from the filename
QString guess_colorspace = config->parseColorSpaceFromString(c->media()->to_footage()->url.toUtf8());
if (!guess_colorspace.isEmpty()) {
input_cs = guess_colorspace;
}
}
}
try {
OCIO::ConstProcessorRcPtr processor = config->getProcessor(input_cs.toUtf8(),
OCIO::ROLE_SCENE_LINEAR);
c->ocio_shader = olive::rendering::SetupOCIO(params.ctx, c->ocio_lut_texture, processor);
} catch (OCIO::Exception& e) {
qWarning() << e.what();
}
}
if (c->ocio_shader != nullptr) {
textureID = olive::rendering::OCIOBlit(c->ocio_shader.get(),
c->ocio_lut_texture,
c->fbo.at(fbo_switcher),
textureID);
fbo_switcher = !fbo_switcher;
}
}
#endif
@@ -640,9 +670,9 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
backend_tex_1 = params.nests.last()->fbo[1].texture();
backend_tex_2 = params.nests.last()->fbo[2].texture();
} else {
back_buffer_1 = params.backend_buffer1;
backend_tex_1 = params.backend_attachment1;
backend_tex_2 = params.backend_attachment2;
back_buffer_1 = params.backend_buffer1->buffer();
backend_tex_1 = params.backend_buffer1->texture();
backend_tex_2 = params.backend_buffer2->texture();
}
// render a backbuffer
@@ -743,7 +773,7 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
if (params.nests.size() > 0) {
draw_clip(params.ctx, params.pipeline, params.nests.last()->fbo[2].buffer(), params.nests.last()->fbo[0].texture(), true);
} else {
draw_clip(params.ctx, params.pipeline, params.backend_buffer2, params.main_attachment, true);
draw_clip(params.ctx, params.pipeline, params.backend_buffer2->buffer(), params.main_buffer->texture(), true);
}
}
@@ -909,6 +939,100 @@ void close_active_clips(Sequence* s) {
}
}
void UpdateOCIOGLState(const ComposeSequenceParams& params)
#ifndef NO_OCIO
QOpenGLShaderProgramPtr olive::rendering::SetupOCIO(QOpenGLContext* ctx,
GLuint& lut_texture,
OCIO::ConstProcessorRcPtr processor)
{
QOpenGLExtraFunctions* xf = ctx->extraFunctions();
// Create LUT texture
xf->glGenTextures(1, &lut_texture);
// Bind LUT
xf->glBindTexture(GL_TEXTURE_3D, lut_texture);
// Set texture parameters
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Allocate storage for texture
xf->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
0, GL_RGB,GL_FLOAT, nullptr);
//
// SET UP GLSL SHADER
//
OCIO::GpuShaderDesc shaderDesc;
shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
shaderDesc.setFunctionName("OCIODisplay");
shaderDesc.setLut3DEdgeLen(OCIO_LUT3D_EDGE_SIZE);
//
// COMPUTE 3D LUT
//
GLfloat* ocio_lut_data = new GLfloat[OCIO_NUM_3D_ENTRIES];
processor->getGpuLut3D(ocio_lut_data, shaderDesc);
// Upload LUT data to texture
xf->glTexSubImage3D(GL_TEXTURE_3D, 0,
0, 0, 0,
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
GL_RGB, GL_FLOAT, ocio_lut_data);
delete [] ocio_lut_data;
// Create OCIO shader code
QString shader_text(processor->getGpuShaderText(shaderDesc));
shader_text.append("\n"
"uniform sampler3D tex2;\n"
"\n"
"vec4 process(vec4 col) {\n"
" return OCIODisplay(col, tex2);\n"
"}\n");
// Get pipeline-based shader to inject OCIO shader into
QOpenGLShaderProgramPtr shader = olive::rendering::GetPipeline(shader_text);
// Release LUT
xf->glBindTexture(GL_TEXTURE_3D, 0);
return shader;
}
GLuint olive::rendering::OCIOBlit(QOpenGLShaderProgram *pipeline,
GLuint lut,
const FramebufferObject& fbo,
GLuint texture)
{
QOpenGLContext* ctx = QOpenGLContext::currentContext();
QOpenGLExtraFunctions* xf = ctx->extraFunctions();
xf->glActiveTexture(GL_TEXTURE2);
xf->glBindTexture(GL_TEXTURE_3D, lut);
xf->glActiveTexture(GL_TEXTURE0);
pipeline->bind();
pipeline->setUniformValue("tex2", 2);
//textureID = draw_clip(params.ctx, pipeline, c->fbo.at(fbo_switcher), textureID, true);
GLuint textureID = draw_clip(ctx, pipeline, fbo, texture, true);
pipeline->release();
xf->glActiveTexture(GL_TEXTURE2);
xf->glBindTexture(GL_TEXTURE_3D, 0);
xf->glActiveTexture(GL_TEXTURE0);
return textureID;
}
#endif
+14 -38
View File
@@ -24,6 +24,10 @@
#include <QOpenGLContext>
#include <QVector>
#include <QOpenGLShaderProgram>
#ifndef NO_OCIO
#include <OpenColorIO/OpenColorIO.h>
namespace OCIO = OCIO_NAMESPACE;
#endif
#include "timeline/sequence.h"
#include "effects/effect.h"
@@ -168,16 +172,7 @@ struct ComposeSequenceParams {
*
* When compose_sequence() is rendering the final image, this framebuffer will be bound.
*/
GLuint main_buffer;
/**
* @brief The attachment to the framebuffer in main_buffer
*
* Used only for video rendering. Never accessed with audio rendering.
*
* The OpenGL texture attached to the framebuffer referenced by main_buffer.
*/
GLuint main_attachment;
const FramebufferObject* main_buffer;
/**
* @brief Backend OpenGL framebuffer 1 used for further processing before rendering to main_buffer
@@ -185,15 +180,7 @@ struct ComposeSequenceParams {
* In some situations, compose_sequence() will do some processing through shaders that requires "ping-ponging"
* between framebuffers. backend_buffer1 and backend_buffer2 are used for this purpose.
*/
GLuint backend_buffer1;
/**
* @brief Backend OpenGL framebuffer 1's texture attachment
*
* The texture that ComposeSequenceParams::backend_buffer1 renders to. Bound and drawn to
* ComposeSequenceParams::backend_buffer2 to "ping-pong" between them and various shaders.
*/
GLuint backend_attachment1;
const FramebufferObject* backend_buffer1;
/**
* @brief Backend OpenGL framebuffer 2 used for further processing before rendering to main_buffer
@@ -201,25 +188,7 @@ struct ComposeSequenceParams {
* In some situations, compose_sequence() will do some processing through shaders that requires "ping-ponging"
* between framebuffers. backend_buffer1 and backend_buffer2 are used for this purpose.
*/
GLuint backend_buffer2;
/**
* @brief Backend OpenGL framebuffer 2's texture attachment
*
* The texture that ComposeSequenceParams::backend_buffer2 renders to. Bound and drawn to
* ComposeSequenceParams::backend_buffer1 to "ping-pong" between them and various shaders.
*/
GLuint backend_attachment2;
/**
* @brief OpenGL shader containing OpenColorIO shader information
*/
QOpenGLShaderProgram* ocio_shader;
/**
* @brief OpenGL texture containing LUT obtained form OpenColorIO
*/
GLuint ocio_lut_texture;
const FramebufferObject* backend_buffer2;
};
/**
@@ -417,6 +386,13 @@ namespace olive {
extern GLfloat flipped_blit_texcoords[];
void Blit(QOpenGLShaderProgram* pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
QOpenGLShaderProgramPtr GetPipeline(const QString &shader_code = QString());
#ifndef NO_OCIO
QOpenGLShaderProgramPtr SetupOCIO(QOpenGLContext *ctx, GLuint &lut_texture, OCIO::ConstProcessorRcPtr processor);
GLuint OCIOBlit(QOpenGLShaderProgram *pipeline,
GLuint lut,
const FramebufferObject& fbo,
GLuint texture);
#endif
}
}
+71 -116
View File
@@ -47,10 +47,13 @@ RenderThread::RenderThread() :
tex_height(-1),
queued(false),
texture_failed(false),
#ifndef NO_OCIO
ocio_lut_texture(0),
ocio_shader(nullptr),
#endif
running(true),
front_buffer_switcher(false)
front_buffer_switcher(false),
ocio_config_date(0)
{
surface.create();
}
@@ -85,6 +88,9 @@ void RenderThread::run() {
}
// create any buffers that don't yet exist
if (!composite_buffer.IsCreated()) {
composite_buffer.Create(ctx, seq->width, seq->height);
}
if (!front_buffer_1.IsCreated()) {
front_buffer_1.Create(ctx, seq->width, seq->height);
}
@@ -113,9 +119,11 @@ void RenderThread::run() {
}
#ifndef NO_OCIO
// If there's no OpenColorIO shader, create it now
// If there's no OpenColorIO shader or the configuration has changed, (re-)create it now
if (olive::CurrentConfig.enable_color_management
&& (ocio_shader == nullptr || ocio_loaded_config != olive::CurrentConfig.ocio_config_path)) {
&& (ocio_shader == nullptr || ocio_config_date != olive::CurrentRuntimeConfig.ocio_config_date)) {
ocio_config_date = olive::CurrentRuntimeConfig.ocio_config_date;
destroy_ocio();
set_up_ocio();
@@ -152,102 +160,43 @@ const GLuint &RenderThread::get_texture()
#ifndef NO_OCIO
void RenderThread::set_up_ocio()
{
// Create LUT texture
ctx->extraFunctions()->glGenTextures(1, &ocio_lut_texture);
// Bind LUT
ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, ocio_lut_texture);
// Set texture parameters
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Allocate storage for texture
ctx->extraFunctions()->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
0, GL_RGB,GL_FLOAT, nullptr);
OCIO::ConstConfigRcPtr config;
// Set current config to the file specified in Config
if (QFileInfo::exists(olive::CurrentConfig.ocio_config_path)) {
config = OCIO::Config::CreateFromFile(olive::CurrentConfig.ocio_config_path.toUtf8());
OCIO::SetCurrentConfig(config);
ocio_loaded_config = olive::CurrentConfig.ocio_config_path;
} else {
config = OCIO::GetCurrentConfig();
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
// Get current OCIO display from Config (or defaults if there is no setting)
QString display = olive::CurrentConfig.ocio_display;
if (display.isEmpty()) {
display = config->getDefaultDisplay();
}
const char* display = config->getDefaultDisplay();
QString view = olive::CurrentConfig.ocio_view;
if (view.isEmpty()) {
view = config->getDefaultView(display.toUtf8());
}
// Get current display stats
OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
transform->setInputColorSpaceName(OCIO::ROLE_SCENE_LINEAR);
transform->setDisplay(display);
transform->setView(config->getDefaultView(display));
transform->setDisplay(display.toUtf8());
transform->setView(view.toUtf8());
OCIO::ConstProcessorRcPtr processor;
OCIO::GpuShaderDesc shaderDesc;
// Get processor for this configuration
if (!olive::CurrentConfig.ocio_look.isEmpty()) {
transform->setLooksOverride(olive::CurrentConfig.ocio_look.toUtf8());
transform->setLooksOverrideEnabled(true);
}
try {
processor = config->getProcessor(transform);
// Using the current configuration, try to get an OCIO processor with a corresponding input and output colorspace
OCIO::ConstProcessorRcPtr processor = config->getProcessor(transform);
// Create a OCIO shader with this processor
ocio_shader = olive::rendering::SetupOCIO(ctx, ocio_lut_texture, processor);
} catch(OCIO::Exception & e) {
qCritical() << e.what();
return;
}
//
// SET UP GLSL SHADER
//
shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
shaderDesc.setFunctionName("OCIODisplay");
shaderDesc.setLut3DEdgeLen(OCIO_LUT3D_EDGE_SIZE);
//
// COMPUTE 3D LUT
//
processor->getGpuLut3D(ocio_lut_data, shaderDesc);
// Upload LUT data to texture
ctx->extraFunctions()->glTexSubImage3D(GL_TEXTURE_3D, 0,
0, 0, 0,
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
GL_RGB, GL_FLOAT, ocio_lut_data);
// Create OCIO shader code
QString shader_text(processor->getGpuShaderText(shaderDesc));
shader_text.append("\n"
"uniform sampler3D tex2;\n"
"\n"
"vec4 process(vec4 col) {\n"
" return OCIODisplay(col, tex2);\n"
"}\n");
// Get pipeline-based shader to inject OCIO shader into
ocio_shader = olive::rendering::GetPipeline(shader_text);
// Release LUT
ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, 0);
}
void RenderThread::destroy_ocio()
@@ -272,38 +221,43 @@ void RenderThread::paint() {
params.playback_speed = 1;
params.blend_mode_program = blend_mode_program.get();
params.pipeline = pipeline_program.get();
#ifndef NO_OCIO
params.ocio_shader = ocio_shader.get();
params.ocio_lut_texture = ocio_lut_texture;
#endif
params.backend_buffer1 = back_buffer_1.buffer();
params.backend_buffer2 = back_buffer_2.buffer();
params.backend_attachment1 = back_buffer_1.texture();
params.backend_attachment2 = back_buffer_2.texture();
params.main_buffer = front_buffer_switcher ? front_buffer_1.buffer() : front_buffer_2.buffer();
params.main_attachment = front_buffer_switcher ? front_buffer_1.texture() : front_buffer_2.texture();
params.backend_buffer1 = &back_buffer_1;
params.backend_buffer2 = &back_buffer_2;
params.main_buffer = &composite_buffer;
// get currently selected gizmos
gizmos = seq->GetSelectedGizmo();
params.gizmos = gizmos;
QOpenGLFunctions* f = ctx->functions();
f->glEnable(GL_BLEND);
// bind composite framebuffer for drawing
f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, composite_buffer.buffer());
// Clear framebuffer to nothing
f->glClearColor(0.0, 0.0, 0.0, 0.0);
f->glClear(GL_COLOR_BUFFER_BIT);
// Compose the current frame
compose_sequence(params);
// Copy composite buffer to front buffer
// First lock the appropriate mutex for exclusivity
QMutex& active_mutex = front_buffer_switcher ? front_mutex1 : front_mutex2;
active_mutex.lock();
ctx->functions()->glEnable(GL_BLEND);
// bind framebuffer for drawing
ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, params.main_buffer);
ctx->functions()->glClearColor(0.0, 0.0, 0.0, 0.0);
ctx->functions()->glClear(GL_COLOR_BUFFER_BIT);
compose_sequence(params);
// Convert linear frame to display color space
olive::rendering::OCIOBlit(ocio_shader.get(),
ocio_lut_texture,
front_buffer_switcher ? front_buffer_1 : front_buffer_2,
composite_buffer.texture());
// flush changes
ctx->functions()->glFinish();
f->glFinish();
ctx->functions()->glDisable(GL_BLEND);
f->glDisable(GL_BLEND);
texture_failed = params.texture_failed;
@@ -314,11 +268,11 @@ void RenderThread::paint() {
// texture failed, try again
queued = true;
} else {
ctx->functions()->glBindFramebuffer(GL_READ_FRAMEBUFFER, params.main_buffer);
f->glBindFramebuffer(GL_READ_FRAMEBUFFER, composite_buffer.buffer());
QImage img(tex_width, tex_height, QImage::Format_RGBA8888);
ctx->functions()->glReadPixels(0, 0, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
f->glReadPixels(0, 0, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
img.save(save_fn);
ctx->functions()->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
f->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
save_fn = "";
}
}
@@ -326,25 +280,25 @@ void RenderThread::paint() {
if (pixel_buffer != nullptr) {
// set main framebuffer to the current read buffer
ctx->functions()->glBindFramebuffer(GL_READ_FRAMEBUFFER, params.main_buffer);
f->glBindFramebuffer(GL_READ_FRAMEBUFFER, composite_buffer.buffer());
// store pixels in buffer
ctx->functions()->glReadPixels(0,
0,
pixel_buffer_linesize == 0 ? tex_width : pixel_buffer_linesize,
tex_height,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixel_buffer);
f->glReadPixels(0,
0,
pixel_buffer_linesize == 0 ? tex_width : pixel_buffer_linesize,
tex_height,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixel_buffer);
// release current read buffer
ctx->functions()->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
f->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
pixel_buffer = nullptr;
}
// release
ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void RenderThread::start_render(QOpenGLContext *share,
@@ -390,6 +344,7 @@ void RenderThread::cancel() {
}
void RenderThread::delete_buffers() {
composite_buffer.Destroy();
front_buffer_1.Destroy();
front_buffer_2.Destroy();
back_buffer_1.Destroy();
+3 -10
View File
@@ -34,14 +34,6 @@
#include "rendering/framebufferobject.h"
#include "qopenglshaderprogramptr.h"
#ifndef NO_OCIO
// copied from source code to OCIODisplay
const int OCIO_LUT3D_EDGE_SIZE = 32;
// copied from source code to OCIODisplay, expanded from 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE
const int OCIO_NUM_3D_ENTRIES = 98304;
#endif
class RenderThread : public QThread {
Q_OBJECT
public:
@@ -80,10 +72,9 @@ private:
void destroy_ocio();
// OpenColorIO variables
float ocio_lut_data[OCIO_NUM_3D_ENTRIES];
GLuint ocio_lut_texture;
QOpenGLShaderProgramPtr ocio_shader;
QString ocio_loaded_config;
qint64 ocio_config_date;
#endif
FramebufferObject front_buffer_1;
@@ -92,6 +83,8 @@ private:
FramebufferObject front_buffer_2;
QMutex front_mutex2;
FramebufferObject composite_buffer;
bool front_buffer_switcher;
QWaitCondition wait_cond_;