Krita Source Code Documentation
Loading...
Searching...
No Matches
OcioDisplayFilter Class Reference

#include <ocio_display_filter_vfx2021.h>

+ Inheritance diagram for OcioDisplayFilter:

Public Member Functions

void approximateForwardTransformation (quint8 *pixels, quint32 numPixels) override
 
void approximateInverseTransformation (quint8 *pixels, quint32 numPixels) override
 
KisExposureGammaCorrectionInterfacecorrectionInterface () const override
 
void filter (quint8 *pixels, quint32 numPixels) override
 
bool lockCurrentColorVisualRepresentation () const override
 
 OcioDisplayFilter (KisExposureGammaCorrectionInterface *interface, QObject *parent=0)
 
QString program () const override
 
void setLockCurrentColorVisualRepresentation (bool value)
 
void setupTextures (GLFunctions *f, QOpenGLShaderProgram *program) const override
 
void updateProcessor ()
 
bool updateShader () override
 
template<class F >
bool updateShaderImpl (F *f)
 
bool useInternalColorManagement () const override
 
 ~OcioDisplayFilter ()
 
- Public Member Functions inherited from KisDisplayFilter
 KisDisplayFilter (QObject *parent=0)
 

Public Attributes

double blackPoint
 
OCIO::ConstConfigRcPtr config
 
const char * displayDevice
 
double exposure
 
bool forceInternalColorManagement
 
double gamma
 
const char * inputColorSpaceName
 
const char * look
 
OCIO_CHANNEL_SWIZZLE swizzle
 
const char * view
 
double whitePoint
 

Private Attributes

OCIO::ConstProcessorRcPtr m_forwardApproximationProcessor
 
OCIO::ConstCPUProcessorRcPtr m_forwardApproximationProcessorCPU
 
KisExposureGammaCorrectionInterfacem_interface
 
bool m_lockCurrentColorVisualRepresentation
 
QString m_lut3dcacheid
 
std::vector< KisTextureEntrym_lut3dTexIDs
 
std::vector< KisTextureUniformm_lut3dUniforms
 
OCIO::ConstProcessorRcPtr m_processor
 
OCIO::ConstCPUProcessorRcPtr m_processorCPU
 
QString m_program
 
OCIO::ConstProcessorRcPtr m_reverseApproximationProcessor
 
OCIO::ConstCPUProcessorRcPtr m_reverseApproximationProcessorCPU
 
QString m_shadercacheid
 
bool m_shaderDirty
 

Detailed Description

Definition at line 56 of file ocio_display_filter_vfx2021.h.

Constructor & Destructor Documentation

◆ OcioDisplayFilter()

OcioDisplayFilter::OcioDisplayFilter ( KisExposureGammaCorrectionInterface * interface,
QObject * parent = 0 )
explicit

Definition at line 47 of file ocio_display_filter_vfx2021.cpp.

48 : KisDisplayFilter(parent)
50 , displayDevice(0)
51 , view(0)
52 , look(0)
53 , swizzle(RGBA)
54 , m_interface(interface)
57 , m_shaderDirty(true)
58{
59}
KisDisplayFilter(QObject *parent=0)
std::vector< KisTextureUniform > m_lut3dUniforms
OCIO_CHANNEL_SWIZZLE swizzle
KisExposureGammaCorrectionInterface * m_interface
std::vector< KisTextureEntry > m_lut3dTexIDs

◆ ~OcioDisplayFilter()

OcioDisplayFilter::~OcioDisplayFilter ( )

Definition at line 61 of file ocio_display_filter_vfx2021.cpp.

62{
63}

Member Function Documentation

◆ approximateForwardTransformation()

void OcioDisplayFilter::approximateForwardTransformation ( quint8 * pixels,
quint32 numPixels )
overridevirtual

Implements KisDisplayFilter.

Definition at line 104 of file ocio_display_filter_vfx2021.cpp.

105{
106 // processes that data _in_ place
108 if (numPixels > 16) {
109 // creation of PackedImageDesc is really slow on Windows due to malloc/free
110 OCIO::PackedImageDesc img(reinterpret_cast<float *>(pixels), numPixels, 1, 4);
112 } else {
113 for (quint32 i = 0; i < numPixels; i++) {
114 m_forwardApproximationProcessorCPU->applyRGBA(reinterpret_cast<float*>(pixels));
115 pixels+=4;
116 }
117 }
118 }
119}
OCIO::ConstProcessorRcPtr m_forwardApproximationProcessor
OCIO::ConstCPUProcessorRcPtr m_forwardApproximationProcessorCPU

References m_forwardApproximationProcessor, and m_forwardApproximationProcessorCPU.

◆ approximateInverseTransformation()

void OcioDisplayFilter::approximateInverseTransformation ( quint8 * pixels,
quint32 numPixels )
overridevirtual

Implements KisDisplayFilter.

Definition at line 87 of file ocio_display_filter_vfx2021.cpp.

88{
89 // processes that data _in_ place
91 if (numPixels > 16) {
92 // creation of PackedImageDesc is really slow on Windows due to malloc/free
93 OCIO::PackedImageDesc img(reinterpret_cast<float *>(pixels), numPixels, 1, 4);
95 } else {
96 for (quint32 i = 0; i < numPixels; i++) {
97 m_reverseApproximationProcessorCPU->applyRGBA(reinterpret_cast<float*>(pixels));
98 pixels+=4;
99 }
100 }
101 }
102}
OCIO::ConstCPUProcessorRcPtr m_reverseApproximationProcessorCPU
OCIO::ConstProcessorRcPtr m_reverseApproximationProcessor

References m_reverseApproximationProcessor, and m_reverseApproximationProcessorCPU.

◆ correctionInterface()

KisExposureGammaCorrectionInterface * OcioDisplayFilter::correctionInterface ( ) const
overridevirtual

Implements KisDisplayFilter.

Definition at line 65 of file ocio_display_filter_vfx2021.cpp.

66{
67 return m_interface;
68}

References m_interface.

◆ filter()

void OcioDisplayFilter::filter ( quint8 * pixels,
quint32 numPixels )
overridevirtual

Implements KisDisplayFilter.

Definition at line 70 of file ocio_display_filter_vfx2021.cpp.

71{
72 // processes that data _in_ place
73 if (m_processor) {
74 if (numPixels > 16) {
75 // creation of PackedImageDesc is really slow on Windows due to malloc/free
76 OCIO::PackedImageDesc img(reinterpret_cast<float *>(pixels), numPixels, 1, 4);
77 m_processorCPU->apply(img);
78 } else {
79 for (quint32 i = 0; i < numPixels; i++) {
80 m_processorCPU->applyRGBA(reinterpret_cast<float*>(pixels));
81 pixels+=4;
82 }
83 }
84 }
85}
OCIO::ConstProcessorRcPtr m_processor
OCIO::ConstCPUProcessorRcPtr m_processorCPU

References m_processor, and m_processorCPU.

◆ lockCurrentColorVisualRepresentation()

bool OcioDisplayFilter::lockCurrentColorVisualRepresentation ( ) const
overridevirtual

◆ program()

QString OcioDisplayFilter::program ( ) const
overridevirtual

Implements KisDisplayFilter.

Definition at line 136 of file ocio_display_filter_vfx2021.cpp.

137{
138 return m_program;
139}

References m_program.

◆ setLockCurrentColorVisualRepresentation()

void OcioDisplayFilter::setLockCurrentColorVisualRepresentation ( bool value)

Definition at line 131 of file ocio_display_filter_vfx2021.cpp.

132{
134}
float value(const T *src, size_t ch)

References m_lockCurrentColorVisualRepresentation, and value().

◆ setupTextures()

void OcioDisplayFilter::setupTextures ( GLFunctions * f,
QOpenGLShaderProgram * program ) const
overridevirtual

Implements KisDisplayFilter.

Definition at line 652 of file ocio_display_filter_vfx2021.cpp.

653{
654 for (unsigned int idx = 0; idx < m_lut3dTexIDs.size(); ++idx) {
655 const auto &data = m_lut3dTexIDs[idx];
656 f->glActiveTexture(GL_TEXTURE0 + 1 + idx);
657 f->glBindTexture(data.m_type, data.m_uid);
658 program->setUniformValue(program->uniformLocation(data.m_samplerName), GLint(1 + idx));
659 }
660
661 for (const KisTextureUniform &uniform : m_lut3dUniforms) {
662 const int m_handle = program->uniformLocation(uniform.m_name);
663
664 const OCIO::GpuShaderDesc::UniformData &m_data = uniform.m_data;
665
666 // Update value.
667 if (m_data.m_getDouble) {
668 program->setUniformValue(m_handle, static_cast<GLfloat>(m_data.m_getDouble()));
669 } else if (m_data.m_getBool) {
670 program->setUniformValue(m_handle, static_cast<GLfloat>(m_data.m_getBool() ? 1.0f : 0.0f));
671 } else if (m_data.m_getFloat3) {
672 program->setUniformValue(m_handle,
673 m_data.m_getFloat3()[0],
674 m_data.m_getFloat3()[1],
675 m_data.m_getFloat3()[2]);
676 } else if (m_data.m_vectorFloat.m_getSize && m_data.m_vectorFloat.m_getVector) {
677 program->setUniformValueArray(m_handle,
678 m_data.m_vectorFloat.m_getVector(),
679 m_data.m_vectorFloat.m_getSize(),
680 1);
681 } else if (m_data.m_vectorInt.m_getSize && m_data.m_vectorInt.m_getVector) {
682 program->setUniformValueArray(m_handle, m_data.m_vectorInt.m_getVector(), m_data.m_vectorInt.m_getSize());
683 } else {
684 errOpenGL << "Uniform" << uniform.m_name << "is not linked to any value";
685 continue;
686 }
687 }
688}
QString program() const override
#define errOpenGL
Definition kis_debug.h:122

References errOpenGL, m_lut3dTexIDs, m_lut3dUniforms, and program().

◆ updateProcessor()

void OcioDisplayFilter::updateProcessor ( )

Look support: As the OCIO docs will tell you, looks are a aesthetic transform that is added onto the mix. A view+display can have it's own assigned Look, or list of looks, and these can be overridden optionally. What the OCIO docs won't tell you is that a display transform won't use the looks attached to it unless "skipColorSpaceConversions" is false... I have no idea what "skipColorSpaceConversions" is beyond what it says on the tin. It is not mentioned in the documentation anywhere. Or on the website. Or how to set it. Or unset it. Why it is apparently set true to begin with. Only that, apparently, this was done with non-color data in mind...

Until there's clear documentation on how to use this feature, I am afraid the override is all we can offer.

Definition at line 141 of file ocio_display_filter_vfx2021.cpp.

142{
143 if (!config) {
144 return;
145 }
146
147 if (!displayDevice) {
148 displayDevice = config->getDefaultDisplay();
149 }
150
151 if (!view) {
152 view = config->getDefaultView(displayDevice);
153 }
154
155 if (!inputColorSpaceName) {
156 inputColorSpaceName = config->getColorSpaceNameByIndex(0);
157 }
158 if (!look) {
159 look = config->getLookNameByIndex(0);
160 }
161
163 return;
164 }
165
166 OCIO::DisplayViewTransformRcPtr transform = OCIO::DisplayViewTransform::Create();
167 transform->setSrc(inputColorSpaceName);
168 transform->setDisplay(displayDevice);
169 transform->setView(view);
170
171 OCIO::LegacyViewingPipelineRcPtr vpt = OCIO::LegacyViewingPipeline::Create();
172
173 vpt->setDisplayViewTransform(transform);
174
191 if (config->getLook(look)) {
192 vpt->setLooksOverride(look);
193 vpt->setLooksOverrideEnabled(true);
194 }
195
196 OCIO::GroupTransformRcPtr approximateTransform = OCIO::GroupTransform::Create();
197
198 // fstop exposure control -- not sure how that translates to our exposure
199 {
200 const double exposureGain = pow(2.0, exposure);
201
202 const double minRange = 0.001;
203 if (qAbs(blackPoint - whitePoint) < minRange) {
204 whitePoint = blackPoint + minRange;
205 }
206
207 const double oldMin[] = {blackPoint, blackPoint, blackPoint, 0.0};
208 const double oldMax[] = {whitePoint, whitePoint, whitePoint, 1.0};
209
210 const double newMin[] = {0.0, 0.0, 0.0, 0.0};
211 const double newMax[] = {exposureGain, exposureGain, exposureGain, 1.0};
212
213 double m44[16];
214 double offset4[4];
215 OCIO::MatrixTransform::Fit(m44, offset4, oldMin, oldMax, newMin, newMax);
216 OCIO::MatrixTransformRcPtr mtx = OCIO::MatrixTransform::Create();
217 mtx->setMatrix(m44);
218 mtx->setOffset(offset4);
219 vpt->setLinearCC(mtx);
220
221 // approximation (no color correction);
222 approximateTransform->appendTransform(mtx);
223 }
224
225 // channel swizzle
226 {
227 int channelHot[4];
228 switch (swizzle) {
229 case LUMINANCE:
230 channelHot[0] = 1;
231 channelHot[1] = 1;
232 channelHot[2] = 1;
233 channelHot[3] = 0;
234 break;
235 case RGBA:
236 channelHot[0] = 1;
237 channelHot[1] = 1;
238 channelHot[2] = 1;
239 channelHot[3] = 1;
240 break;
241 case R:
242 channelHot[0] = 1;
243 channelHot[1] = 0;
244 channelHot[2] = 0;
245 channelHot[3] = 0;
246 break;
247 case G:
248 channelHot[0] = 0;
249 channelHot[1] = 1;
250 channelHot[2] = 0;
251 channelHot[3] = 0;
252 break;
253 case B:
254 channelHot[0] = 0;
255 channelHot[1] = 0;
256 channelHot[2] = 1;
257 channelHot[3] = 0;
258 break;
259 case A:
260 channelHot[0] = 0;
261 channelHot[1] = 0;
262 channelHot[2] = 0;
263 channelHot[3] = 1;
264 default:;
265 }
266 double lumacoef[3];
267 config->getDefaultLumaCoefs(lumacoef);
268 double m44[16];
269 double offset[4];
270 OCIO::MatrixTransform::View(m44, offset, channelHot, lumacoef);
271 OCIO::MatrixTransformRcPtr swizzleTransform = OCIO::MatrixTransform::Create();
272 swizzleTransform->setMatrix(m44);
273 swizzleTransform->setOffset(offset);
274 vpt->setChannelView(swizzleTransform);
275 }
276
277 // Post-display transform gamma
278 {
279 double exponent = 1.0 / std::max(1e-6, gamma);
280 const double exponent4f[] = {exponent, exponent, exponent, exponent};
281 OCIO::ExponentTransformRcPtr expTransform = OCIO::ExponentTransform::Create();
282 expTransform->setValue(exponent4f);
283 vpt->setDisplayCC(expTransform);
284
285 // approximation (no color correction);
286 approximateTransform->appendTransform(expTransform);
287 }
288
289 try {
291 m_processor = vpt->getProcessor(config, config->getCurrentContext());
292 m_processorCPU = m_processor->getDefaultCPUProcessor();
293 } catch (OCIO::Exception &e) {
294 // XXX: How to not break the OCIO shader now?
295 errKrita << "OCIO exception while parsing the current context:" << e.what();
296 m_shaderDirty = false;
297 return;
298 }
299
300 m_forwardApproximationProcessor = config->getProcessor(approximateTransform, OCIO::TRANSFORM_DIR_FORWARD);
302
303 try {
304 m_reverseApproximationProcessor = config->getProcessor(approximateTransform, OCIO::TRANSFORM_DIR_INVERSE);
306 } catch (...) {
307 warnKrita << "OCIO inverted matrix does not exist!";
308 // m_reverseApproximationProcessor;
309 }
310
311 m_shaderDirty = true;
312}
OCIO::ConstConfigRcPtr config
#define errKrita
Definition kis_debug.h:107
#define warnKrita
Definition kis_debug.h:87

References A, B, blackPoint, config, displayDevice, errKrita, exposure, G, gamma, inputColorSpaceName, look, LUMINANCE, m_forwardApproximationProcessor, m_forwardApproximationProcessorCPU, m_processor, m_processorCPU, m_reverseApproximationProcessor, m_reverseApproximationProcessorCPU, m_shaderDirty, R, RGBA, swizzle, view, warnKrita, and whitePoint.

◆ updateShader()

bool OcioDisplayFilter::updateShader ( )
overridevirtual
Returns
true if the shader should be recompiled

Implements KisDisplayFilter.

Definition at line 314 of file ocio_display_filter_vfx2021.cpp.

315{
317 QOpenGLContext *ctx = QOpenGLContext::currentContext();
318
320
321 if (ctx->format().majorVersion() >= 3) {
322 QOpenGLExtraFunctions *f = ctx->extraFunctions();
323 if (f) {
324 return updateShaderImpl(f);
325 }
326 } else if (ctx->hasExtension("GL_OES_texture_float")
327 && (ctx->hasExtension("GL_EXT_texture_storage") || ctx->hasExtension("EXT_color_buffer_float"))
328 && ctx->hasExtension("GL_OES_texture_float_linear")) {
329 QOpenGLExtraFunctions *f = ctx->extraFunctions();
330 if (f) {
331 return updateShaderImpl(f);
332 }
333 } else {
334 dbgKrita << "OcioDisplayFilter::updateShader"
335 << "OpenGL ES v2+ support detected but no OES_texture_float,"
336 "GL_EXT_color_buffer_float or GL_EXT_texture_storage, or GL_OES_texture_float_linear were found";
337 return false;
338 }
339#if defined(QT_OPENGL_3)
340 } else if (KisOpenGL::hasOpenGL3()) {
341#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
342 QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
343#else
344 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
345 profile.setVersion(3,2);
346 QOpenGLFunctions_3_2_Core *f = reinterpret_cast<QOpenGLFunctions_3_2_Core *>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
347#endif
348 if (f) {
349 return updateShaderImpl(f);
350 }
351#endif
352 }
353
355#if defined(QT_OPENGL_3)
356#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
357#if defined(Q_OS_MAC) && defined(QT_OPENGL_3_2)
358 QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
359#else
360 QOpenGLFunctions_3_0 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_0>();
361#endif
362#else
363#if defined(Q_OS_MAC) && defined(QT_OPENGL_3_2)
364 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
365 profile.setVersion(3,2);
366 QOpenGLFunctions_3_2_Core *f = reinterpret_cast<QOpenGLFunctions_3_2_Core *>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
367#else
368 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
369 profile.setVersion(3,0);
370 QOpenGLFunctions_3_0 *f = reinterpret_cast<QOpenGLFunctions_3_0 *>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
371#endif
372
373#endif
374 if (f) {
375 return updateShaderImpl(f);
376 }
377#endif
378 }
379#if !defined(QT_OPENGL_ES_2)
380#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
381 QOpenGLFunctions_2_0 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_0>();
382#else
383 QOpenGLVersionProfile profile(QOpenGLContext::currentContext()->surface()->format());
384 profile.setVersion(2,0);
385 QOpenGLFunctions_2_0 *f = reinterpret_cast<QOpenGLFunctions_2_0 *>(QOpenGLVersionFunctionsFactory::get(profile, QOpenGLContext::currentContext()));
386#endif
387 if (f) {
388 return updateShaderImpl(f);
389 }
390#endif
391
392 return false;
393}
static bool hasOpenGLES()
static bool supportsLoD()
static bool hasOpenGL3()
#define KIS_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:85
#define dbgKrita
Definition kis_debug.h:45

References dbgKrita, KisOpenGL::hasOpenGL3(), KisOpenGL::hasOpenGLES(), KIS_ASSERT_RECOVER_RETURN_VALUE, KisOpenGL::supportsLoD(), and updateShaderImpl().

◆ updateShaderImpl()

template<class F >
bool OcioDisplayFilter::updateShaderImpl ( F * f)

Definition at line 396 of file ocio_display_filter_vfx2021.cpp.

397{
398 // check whether we are allowed to use shaders -- though that should
399 // work for everyone these days
400 KisConfig cfg(true);
401 if (!cfg.useOpenGL())
402 return false;
403
404 if (!m_shaderDirty)
405 return false;
406
407 if (!f) {
408 qWarning() << "Failed to get valid OpenGL functions for OcioDisplayFilter!";
409 return false;
410 }
411
412 bool shouldRecompileShader = false;
413
414 // Step 1: Create a GPU Shader Description
415 OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc();
416
417#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
419 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_3_0);
420 } else {
421 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_1_0);
422 }
423#else
425 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_3);
426 } else {
427 shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
428 }
429#endif
430
431 shaderDesc->setFunctionName("OCIODisplay");
432 shaderDesc->setResourcePrefix("ocio_");
433
434 // Step 2: Compute the 3D LUT
435#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
436 // ensure the new GPU pipeline is used with our GLES3 patch
437 // this way users won't run into errors when using Angle along with OCIO
438 const auto gpu = m_processor->getOptimizedGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_DEFAULT);
439#else
440 const int lut3DEdgeSize = cfg.ocioLutEdgeSize();
441 const auto gpu =
442 m_processor->getOptimizedLegacyGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_DEFAULT, lut3DEdgeSize);
443#endif
444
445 gpu->extractGpuShaderInfo(shaderDesc);
446
447 // OCIO v2 assumes you'll use the OglApp helpers
448 // these are unusable from a Qt backend, because they rely on GLUT/GLFW
449 // ociodisplay original pipeline:
450 // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/508b3f4a0618435aeed2f45058208bdfa99e0887/src/apps/ociodisplay/main.cpp
451 // ociodisplay new pipeline is a single call:
452 // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/ffddc3341f5775c7866fe2c93275e1d5e0b0540f/src/apps/ociodisplay/main.cpp#L427
453 // we need to replicate this loop:
454 // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/dd59baf555656e09f52c3838e85ccf154497ec1d/src/libutils/oglapphelpers/oglapp.cpp#L191-L223
455 // calls functions from here:
456 // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/dd59baf555656e09f52c3838e85ccf154497ec1d/src/libutils/oglapphelpers/glsl.cpp
457
458 for (const auto &tex : m_lut3dTexIDs) {
459 f->glDeleteTextures(1, &tex.m_uid);
460 }
461
462 m_lut3dTexIDs.clear();
463
464 // This is the first available index for the textures.
465 unsigned currIndex = 1;
466
467 // Process the 3D LUT first.
468
469 const unsigned maxTexture3D = shaderDesc->getNum3DTextures();
470 for (unsigned idx = 0; idx < maxTexture3D; ++idx) {
471 // 1. Get the information of the 3D LUT.
472
473 const char *textureName = nullptr;
474 const char *samplerName = nullptr;
475 unsigned edgelen = 0;
476 OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
477 shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, interpolation);
478
479 if (!textureName || !*textureName || !samplerName || !*samplerName || edgelen == 0) {
480 errOpenGL << "The texture data is corrupted";
481 return false;
482 }
483
484 const float *values = nullptr;
485 shaderDesc->get3DTextureValues(idx, values);
486 if (!values) {
487 errOpenGL << "The texture values are missing";
488 return false;
489 }
490
491 // 2. Allocate the 3D LUT.
492
493 unsigned texId = 0;
494 {
495 if (values == nullptr) {
496 errOpenGL << "3D LUT" << idx << "Missing texture data";
497 return false;
498 }
499
500 f->glGenTextures(1, &texId);
501
502 f->glActiveTexture(GL_TEXTURE0 + currIndex);
503
504 f->glBindTexture(GL_TEXTURE_3D, texId);
505
506 {
507 if (interpolation == OCIO::INTERP_NEAREST) {
508 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
509 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
510 } else {
511 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
512 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
513 }
514
515 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
516 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
517 f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
518 }
519
520 f->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB32F_ARB, edgelen, edgelen, edgelen, 0, GL_RGB, GL_FLOAT, values);
521 }
522
523 // 3. Keep the texture id & name for the later enabling.
524
525 m_lut3dTexIDs.push_back({texId, textureName, samplerName, GL_TEXTURE_3D});
526
527 currIndex++;
528 }
529
530 // Process the 1D LUTs.
531
532 const unsigned maxTexture2D = shaderDesc->getNumTextures();
533 for (unsigned idx = 0; idx < maxTexture2D; ++idx) {
534 // 1. Get the information of the 1D LUT.
535
536 const char *textureName = nullptr;
537 const char *samplerName = nullptr;
538 unsigned width = 0;
539 unsigned height = 0;
540 OCIO::GpuShaderDesc::TextureType channel = OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL;
541 OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
542
543#if OCIO_VERSION_HEX >= 0x2030000
544 OCIO::GpuShaderCreator::TextureDimensions dimensions;
545 shaderDesc->getTexture(idx, textureName, samplerName, width, height, channel, dimensions, interpolation);
546#else
547 shaderDesc->getTexture(idx, textureName, samplerName, width, height, channel, interpolation);
548#endif
549
550 if (!textureName || !*textureName || !samplerName || !*samplerName || width == 0) {
551 errOpenGL << "The texture data is corrupted";
552 return false;
553 }
554
555 const float *values = nullptr;
556 shaderDesc->getTextureValues(idx, values);
557 if (!values) {
558 errOpenGL << "The texture values are missing";
559 return false;
560 }
561
562 // 2. Allocate the 1D LUT (a 2D texture is needed to hold large LUTs).
563
564 unsigned texId = 0;
565 {
566 if (values == nullptr) {
567 errOpenGL << "1D LUT" << idx << "Missing texture data.";
568 return false;
569 }
570
571 unsigned internalformat = GL_RGB32F_ARB;
572 unsigned format = GL_RGB;
573
574 if (channel == OCIO::GpuShaderCreator::TEXTURE_RED_CHANNEL) {
575 internalformat = GL_R32F;
576 format = GL_RED;
577 }
578
579 f->glGenTextures(1, &texId);
580
581 f->glActiveTexture(GL_TEXTURE0 + currIndex);
582
583#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
584#else
585 // 1D Textures are unsupported by OpenGL ES.
586 // https://github.com/AcademySoftwareFoundation/OpenColorIO/issues/1486
587 if (height > 1) {
588#endif
589 f->glBindTexture(GL_TEXTURE_2D, texId);
590
591 {
592 if (interpolation == OCIO::INTERP_NEAREST) {
593 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
594 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
595 } else {
596 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
597 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
598 }
599
600 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
601 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
602 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
603 }
604
605 f->glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_FLOAT, values);
606#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
607#else
608 } else {
609 errOpenGL << "1D texture detected @" << idx << ", not supported by OpenGLES";
610 return false;
611 }
612#endif
613 }
614
615 // 3. Keep the texture id & name for the later enabling.
616
617 unsigned type = GL_TEXTURE_2D;
618 m_lut3dTexIDs.push_back({texId, textureName, samplerName, type});
619 currIndex++;
620 }
621
622 // Step 3: Generate the shader text
623 QString shaderCacheID = QString::fromLatin1(shaderDesc->getCacheID());
624 if (m_program.isEmpty() || shaderCacheID != m_shadercacheid) {
625 // dbgKrita << "Computing Shader " << m_shadercacheid;
626
627 m_shadercacheid = shaderCacheID;
628
629 m_program = QString::fromLatin1("%1\n").arg(shaderDesc->getShaderText());
630 shouldRecompileShader = true;
631 }
632
633 // Step 4: mirror and bind uniforms
634 m_lut3dUniforms.clear();
635
636 const unsigned maxUniforms = shaderDesc->getNumUniforms();
637 for (unsigned idx = 0; idx < maxUniforms; ++idx) {
638 OCIO::GpuShaderDesc::UniformData data;
639 const char *name = shaderDesc->getUniform(idx, data);
640 if (data.m_type == OCIO::UNIFORM_UNKNOWN) {
641 errOpenGL << "Uniform" << idx << "has an unknown type";
642 return false;
643 }
644 // Transfer uniform.
645 m_lut3dUniforms.push_back({name, data});
646 }
647
648 m_shaderDirty = false;
649 return shouldRecompileShader;
650}
#define GL_CLAMP_TO_EDGE
const char * name(StandardAction id)

References errOpenGL, GL_CLAMP_TO_EDGE, m_lut3dTexIDs, m_lut3dUniforms, m_processor, m_program, m_shadercacheid, m_shaderDirty, KisConfig::ocioLutEdgeSize(), KisOpenGL::supportsLoD(), and KisConfig::useOpenGL().

◆ useInternalColorManagement()

bool OcioDisplayFilter::useInternalColorManagement ( ) const
overridevirtual

Implements KisDisplayFilter.

Definition at line 121 of file ocio_display_filter_vfx2021.cpp.

References forceInternalColorManagement.

Member Data Documentation

◆ blackPoint

double OcioDisplayFilter::blackPoint

Definition at line 92 of file ocio_display_filter_vfx2021.h.

◆ config

OCIO::ConstConfigRcPtr OcioDisplayFilter::config

Definition at line 83 of file ocio_display_filter_vfx2021.h.

◆ displayDevice

const char* OcioDisplayFilter::displayDevice

Definition at line 86 of file ocio_display_filter_vfx2021.h.

◆ exposure

double OcioDisplayFilter::exposure

Definition at line 90 of file ocio_display_filter_vfx2021.h.

◆ forceInternalColorManagement

bool OcioDisplayFilter::forceInternalColorManagement

Definition at line 94 of file ocio_display_filter_vfx2021.h.

◆ gamma

double OcioDisplayFilter::gamma

Definition at line 91 of file ocio_display_filter_vfx2021.h.

◆ inputColorSpaceName

const char* OcioDisplayFilter::inputColorSpaceName

Definition at line 85 of file ocio_display_filter_vfx2021.h.

◆ look

const char* OcioDisplayFilter::look

Definition at line 88 of file ocio_display_filter_vfx2021.h.

◆ m_forwardApproximationProcessor

OCIO::ConstProcessorRcPtr OcioDisplayFilter::m_forwardApproximationProcessor
private

Definition at line 99 of file ocio_display_filter_vfx2021.h.

◆ m_forwardApproximationProcessorCPU

OCIO::ConstCPUProcessorRcPtr OcioDisplayFilter::m_forwardApproximationProcessorCPU
private

Definition at line 103 of file ocio_display_filter_vfx2021.h.

◆ m_interface

KisExposureGammaCorrectionInterface* OcioDisplayFilter::m_interface
private

Definition at line 105 of file ocio_display_filter_vfx2021.h.

◆ m_lockCurrentColorVisualRepresentation

bool OcioDisplayFilter::m_lockCurrentColorVisualRepresentation
private

Definition at line 107 of file ocio_display_filter_vfx2021.h.

◆ m_lut3dcacheid

QString OcioDisplayFilter::m_lut3dcacheid
private

Definition at line 111 of file ocio_display_filter_vfx2021.h.

◆ m_lut3dTexIDs

std::vector<KisTextureEntry> OcioDisplayFilter::m_lut3dTexIDs
private

Definition at line 110 of file ocio_display_filter_vfx2021.h.

◆ m_lut3dUniforms

std::vector<KisTextureUniform> OcioDisplayFilter::m_lut3dUniforms
private

Definition at line 113 of file ocio_display_filter_vfx2021.h.

◆ m_processor

OCIO::ConstProcessorRcPtr OcioDisplayFilter::m_processor
private

Definition at line 97 of file ocio_display_filter_vfx2021.h.

◆ m_processorCPU

OCIO::ConstCPUProcessorRcPtr OcioDisplayFilter::m_processorCPU
private

Definition at line 101 of file ocio_display_filter_vfx2021.h.

◆ m_program

QString OcioDisplayFilter::m_program
private

Definition at line 109 of file ocio_display_filter_vfx2021.h.

◆ m_reverseApproximationProcessor

OCIO::ConstProcessorRcPtr OcioDisplayFilter::m_reverseApproximationProcessor
private

Definition at line 98 of file ocio_display_filter_vfx2021.h.

◆ m_reverseApproximationProcessorCPU

OCIO::ConstCPUProcessorRcPtr OcioDisplayFilter::m_reverseApproximationProcessorCPU
private

Definition at line 102 of file ocio_display_filter_vfx2021.h.

◆ m_shadercacheid

QString OcioDisplayFilter::m_shadercacheid
private

Definition at line 112 of file ocio_display_filter_vfx2021.h.

◆ m_shaderDirty

bool OcioDisplayFilter::m_shaderDirty
private

Definition at line 115 of file ocio_display_filter_vfx2021.h.

◆ swizzle

OCIO_CHANNEL_SWIZZLE OcioDisplayFilter::swizzle

Definition at line 89 of file ocio_display_filter_vfx2021.h.

◆ view

const char* OcioDisplayFilter::view

Definition at line 87 of file ocio_display_filter_vfx2021.h.

◆ whitePoint

double OcioDisplayFilter::whitePoint

Definition at line 93 of file ocio_display_filter_vfx2021.h.


The documentation for this class was generated from the following files: