mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-18 22:54:00 +00:00
1081 lines
40 KiB
Diff
1081 lines
40 KiB
Diff
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||
|
index e06a3bd0ab..e02b1ad196 100644
|
||
|
--- a/CMakeLists.txt
|
||
|
+++ b/CMakeLists.txt
|
||
|
@@ -705,13 +705,13 @@ if (FFTW3_FOUND)
|
||
|
list (APPEND ANDROID_EXTRA_LIBS ${FFTW3_LIBRARY})
|
||
|
endif()
|
||
|
|
||
|
-find_package(OCIO)
|
||
|
-set_package_properties(OCIO PROPERTIES
|
||
|
+find_package(OpenColorIO)
|
||
|
+set_package_properties(OpenColorIO PROPERTIES
|
||
|
DESCRIPTION "The OpenColorIO Library"
|
||
|
URL "https://www.opencolorio.org"
|
||
|
TYPE OPTIONAL
|
||
|
PURPOSE "Required by the Krita LUT docker")
|
||
|
-macro_bool_to_01(OCIO_FOUND HAVE_OCIO)
|
||
|
+macro_bool_to_01(OpenColorIO_FOUND HAVE_OCIO)
|
||
|
|
||
|
set_package_properties(PythonLibrary PROPERTIES
|
||
|
DESCRIPTION "Python Library"
|
||
|
diff --git a/krita/data/shaders/highq_downscale.frag b/krita/data/shaders/highq_downscale.frag
|
||
|
index bb2a47c2a3..73c95ebfa8 100644
|
||
|
--- a/krita/data/shaders/highq_downscale.frag
|
||
|
+++ b/krita/data/shaders/highq_downscale.frag
|
||
|
@@ -3,10 +3,6 @@
|
||
|
*/
|
||
|
uniform sampler2D texture0;
|
||
|
|
||
|
-#ifdef USE_OCIO
|
||
|
-uniform sampler3D texture1;
|
||
|
-#endif
|
||
|
-
|
||
|
in vec4 v_textureCoordinate;
|
||
|
out vec4 fragColor;
|
||
|
|
||
|
@@ -119,7 +115,7 @@ void main() {
|
||
|
}
|
||
|
|
||
|
#ifdef USE_OCIO
|
||
|
- fragColor = OCIODisplay(col, texture1);
|
||
|
+ fragColor = OCIODisplay(col);
|
||
|
#else /* USE_OCIO */
|
||
|
fragColor = col;
|
||
|
#endif /* USE_OCIO */
|
||
|
diff --git a/libs/ui/canvas/kis_display_filter.h b/libs/ui/canvas/kis_display_filter.h
|
||
|
index a2ae5ab584..e96506d892 100644
|
||
|
--- a/libs/ui/canvas/kis_display_filter.h
|
||
|
+++ b/libs/ui/canvas/kis_display_filter.h
|
||
|
@@ -26,6 +26,9 @@
|
||
|
|
||
|
struct KisExposureGammaCorrectionInterface;
|
||
|
|
||
|
+class QOpenGLFunctions;
|
||
|
+class QOpenGLShaderProgram;
|
||
|
+
|
||
|
/**
|
||
|
* @brief The KisDisplayFilter class is the base class for filters that
|
||
|
* are applied by the canvas to the projection before displaying.
|
||
|
@@ -37,7 +40,7 @@ public:
|
||
|
explicit KisDisplayFilter(QObject *parent = 0);
|
||
|
|
||
|
virtual QString program() const = 0;
|
||
|
- virtual GLuint lutTexture() const = 0;
|
||
|
+ virtual void setupTextures(QOpenGLFunctions *f, QOpenGLShaderProgram *program) const = 0;
|
||
|
virtual void filter(quint8 *pixels, quint32 numPixels) = 0;
|
||
|
virtual void approximateInverseTransformation(quint8 *pixels, quint32 numPixels) = 0;
|
||
|
virtual void approximateForwardTransformation(quint8 *pixels, quint32 numPixels) = 0;
|
||
|
diff --git a/libs/ui/opengl/kis_opengl_canvas2.cpp b/libs/ui/opengl/kis_opengl_canvas2.cpp
|
||
|
index 69bd84000f..50acab76bf 100644
|
||
|
--- a/libs/ui/opengl/kis_opengl_canvas2.cpp
|
||
|
+++ b/libs/ui/opengl/kis_opengl_canvas2.cpp
|
||
|
@@ -947,9 +947,7 @@ void KisOpenGLCanvas2::drawImage(const QRect &updateRect)
|
||
|
}
|
||
|
|
||
|
if (d->displayFilter) {
|
||
|
- glActiveTexture(GL_TEXTURE0 + 1);
|
||
|
- glBindTexture(GL_TEXTURE_3D, d->displayFilter->lutTexture());
|
||
|
- d->displayShader->setUniformValue(d->displayShader->location(Uniform::Texture1), 1);
|
||
|
+ d->displayFilter->setupTextures(this, d->displayShader);
|
||
|
}
|
||
|
|
||
|
glActiveTexture(GL_TEXTURE0);
|
||
|
diff --git a/libs/ui/opengl/kis_opengl_shader_loader.cpp b/libs/ui/opengl/kis_opengl_shader_loader.cpp
|
||
|
index 8513617815..75a4f08ba3 100644
|
||
|
--- a/libs/ui/opengl/kis_opengl_shader_loader.cpp
|
||
|
+++ b/libs/ui/opengl/kis_opengl_shader_loader.cpp
|
||
|
@@ -150,6 +150,7 @@ KisShaderProgram *KisOpenGLShaderLoader::loadDisplayShader(QSharedPointer<KisDis
|
||
|
bool haveDisplayFilter = displayFilter && !displayFilter->program().isEmpty();
|
||
|
if (haveDisplayFilter) {
|
||
|
fragHeader.append("#define USE_OCIO\n");
|
||
|
+ fragHeader.append("#define USE_OCIO_V2\n");
|
||
|
fragHeader.append(displayFilter->program().toLatin1());
|
||
|
}
|
||
|
|
||
|
diff --git a/plugins/dockers/lut/CMakeLists.txt b/plugins/dockers/lut/CMakeLists.txt
|
||
|
index 01844be146..795c99162d 100644
|
||
|
--- a/plugins/dockers/lut/CMakeLists.txt
|
||
|
+++ b/plugins/dockers/lut/CMakeLists.txt
|
||
|
@@ -17,5 +17,5 @@ ki18n_wrap_ui(KRITA_LUTDOCKER_SOURCES
|
||
|
|
||
|
add_library(kritalutdocker MODULE ${KRITA_LUTDOCKER_SOURCES})
|
||
|
|
||
|
-target_link_libraries(kritalutdocker kritaui ${Boost_SYSTEM_LIBRARY} ${OCIO_LIBRARIES})
|
||
|
+target_link_libraries(kritalutdocker kritaui ${Boost_SYSTEM_LIBRARY} OpenColorIO::OpenColorIO)
|
||
|
install(TARGETS kritalutdocker DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
|
||
|
diff --git a/plugins/dockers/lut/lutdocker_dock.cpp b/plugins/dockers/lut/lutdocker_dock.cpp
|
||
|
index c7e68dce06..3c57144c9d 100644
|
||
|
--- a/plugins/dockers/lut/lutdocker_dock.cpp
|
||
|
+++ b/plugins/dockers/lut/lutdocker_dock.cpp
|
||
|
@@ -56,12 +56,12 @@
|
||
|
#include <KisSqueezedComboBox.h>
|
||
|
#include "kis_signals_blocker.h"
|
||
|
#include "krita_utils.h"
|
||
|
+#include <KisOcioConfiguration.h>
|
||
|
|
||
|
-#include "ocio_display_filter.h"
|
||
|
-#include "black_white_point_chooser.h"
|
||
|
-#include "KisOcioConfiguration.h"
|
||
|
#include <opengl/KisOpenGLModeProber.h>
|
||
|
|
||
|
+#include "black_white_point_chooser.h"
|
||
|
+
|
||
|
|
||
|
OCIO::ConstConfigRcPtr defaultRawProfile()
|
||
|
{
|
||
|
@@ -231,6 +231,8 @@ void LutDockerDock::slotUpdateIcons()
|
||
|
{
|
||
|
m_btnConvertCurrentColor->setIcon(KisIconUtils::loadIcon("krita_tool_freehand"));
|
||
|
m_btmShowBWConfiguration->setIcon(KisIconUtils::loadIcon("properties"));
|
||
|
+ m_lblOcioVersion->setText(OCIO_VERSION_FULL_STR);
|
||
|
+ m_lblOcioVersion->setEnabled(false);
|
||
|
}
|
||
|
|
||
|
void LutDockerDock::slotShowBWConfiguration()
|
||
|
diff --git a/plugins/dockers/lut/ocio_display_filter.cpp b/plugins/dockers/lut/ocio_display_filter.cpp
|
||
|
index 33afb01f1e..e429e3c2f4 100644
|
||
|
--- a/plugins/dockers/lut/ocio_display_filter.cpp
|
||
|
+++ b/plugins/dockers/lut/ocio_display_filter.cpp
|
||
|
@@ -1,38 +1,29 @@
|
||
|
/*
|
||
|
- * Copyright (c) 2012 Boudewijn Rempt <boud@valdyas.org>
|
||
|
+ * SPDX-FileCopyrightText: 2012 Boudewijn Rempt <boud@valdyas.org>
|
||
|
+ * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
|
||
|
*
|
||
|
- * 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 2 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, write to the Free Software
|
||
|
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
*/
|
||
|
+
|
||
|
#include "ocio_display_filter.h"
|
||
|
-#include <math.h>
|
||
|
-#include <cstdlib>
|
||
|
+
|
||
|
+#include <QOpenGLContext>
|
||
|
+#include <QOpenGLExtraFunctions>
|
||
|
+#include <QOpenGLFunctions_2_0>
|
||
|
+#include <QOpenGLFunctions_3_0>
|
||
|
+#include <QOpenGLFunctions_3_2_Core>
|
||
|
+
|
||
|
#include <cmath>
|
||
|
-#include <cstdio>
|
||
|
#include <cstring>
|
||
|
-#include <iostream>
|
||
|
-#include <fstream>
|
||
|
-#include <sstream>
|
||
|
|
||
|
#include <kis_config.h>
|
||
|
-
|
||
|
+#include <kis_debug.h>
|
||
|
#include <opengl/kis_opengl.h>
|
||
|
-#include <QOpenGLContext>
|
||
|
-#include <QOpenGLFunctions_3_2_Core>
|
||
|
-#include <QOpenGLFunctions_3_0>
|
||
|
-#include <QOpenGLFunctions_2_0>
|
||
|
-#include <QOpenGLExtraFunctions>
|
||
|
+
|
||
|
+#if defined(QT_OPENGL_ES_2)
|
||
|
+#define GL_RGBA32F_ARB GL_RGBA32F_EXT
|
||
|
+#define GL_RGB32F_ARB GL_RGB32F_EXT
|
||
|
+#endif
|
||
|
|
||
|
OcioDisplayFilter::OcioDisplayFilter(KisExposureGammaCorrectionInterface *interface, QObject *parent)
|
||
|
: KisDisplayFilter(parent)
|
||
|
@@ -42,7 +33,8 @@ OcioDisplayFilter::OcioDisplayFilter(KisExposureGammaCorrectionInterface *interf
|
||
|
, look(0)
|
||
|
, swizzle(RGBA)
|
||
|
, m_interface(interface)
|
||
|
- , m_lut3dTexID(0)
|
||
|
+ , m_lut3dTexIDs()
|
||
|
+ , m_lut3dUniforms()
|
||
|
, m_shaderDirty(true)
|
||
|
{
|
||
|
}
|
||
|
@@ -51,7 +43,7 @@ OcioDisplayFilter::~OcioDisplayFilter()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
-KisExposureGammaCorrectionInterface* OcioDisplayFilter::correctionInterface() const
|
||
|
+KisExposureGammaCorrectionInterface *OcioDisplayFilter::correctionInterface() const
|
||
|
{
|
||
|
return m_interface;
|
||
|
}
|
||
|
@@ -60,8 +52,8 @@ void OcioDisplayFilter::filter(quint8 *pixels, quint32 numPixels)
|
||
|
{
|
||
|
// processes that data _in_ place
|
||
|
if (m_processor) {
|
||
|
- OCIO::PackedImageDesc img(reinterpret_cast<float*>(pixels), numPixels, 1, 4);
|
||
|
- m_processor->apply(img);
|
||
|
+ OCIO::PackedImageDesc img(reinterpret_cast<float *>(pixels), numPixels, 1, 4);
|
||
|
+ m_processor->getDefaultCPUProcessor()->apply(img);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -69,8 +61,8 @@ void OcioDisplayFilter::approximateInverseTransformation(quint8 *pixels, quint32
|
||
|
{
|
||
|
// processes that data _in_ place
|
||
|
if (m_revereseApproximationProcessor) {
|
||
|
- OCIO::PackedImageDesc img(reinterpret_cast<float*>(pixels), numPixels, 1, 4);
|
||
|
- m_revereseApproximationProcessor->apply(img);
|
||
|
+ OCIO::PackedImageDesc img(reinterpret_cast<float *>(pixels), numPixels, 1, 4);
|
||
|
+ m_revereseApproximationProcessor->getDefaultCPUProcessor()->apply(img);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -78,8 +70,8 @@ void OcioDisplayFilter::approximateForwardTransformation(quint8 *pixels, quint32
|
||
|
{
|
||
|
// processes that data _in_ place
|
||
|
if (m_forwardApproximationProcessor) {
|
||
|
- OCIO::PackedImageDesc img(reinterpret_cast<float*>(pixels), numPixels, 1, 4);
|
||
|
- m_forwardApproximationProcessor->apply(img);
|
||
|
+ OCIO::PackedImageDesc img(reinterpret_cast<float *>(pixels), numPixels, 1, 4);
|
||
|
+ m_forwardApproximationProcessor->getDefaultCPUProcessor()->apply(img);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -103,11 +95,6 @@ QString OcioDisplayFilter::program() const
|
||
|
return m_program;
|
||
|
}
|
||
|
|
||
|
-GLuint OcioDisplayFilter::lutTexture() const
|
||
|
-{
|
||
|
- return m_lut3dTexID;
|
||
|
-}
|
||
|
-
|
||
|
void OcioDisplayFilter::updateProcessor()
|
||
|
{
|
||
|
if (!config) {
|
||
|
@@ -126,18 +113,22 @@ void OcioDisplayFilter::updateProcessor()
|
||
|
inputColorSpaceName = config->getColorSpaceNameByIndex(0);
|
||
|
}
|
||
|
if (!look) {
|
||
|
- look = config->getLookNameByIndex(0);
|
||
|
+ look = config->getLookNameByIndex(0);
|
||
|
}
|
||
|
|
||
|
if (!displayDevice || !view || !inputColorSpaceName) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
|
||
|
- transform->setInputColorSpaceName(inputColorSpaceName);
|
||
|
+ OCIO::DisplayViewTransformRcPtr transform = OCIO::DisplayViewTransform::Create();
|
||
|
+ transform->setSrc(inputColorSpaceName);
|
||
|
transform->setDisplay(displayDevice);
|
||
|
transform->setView(view);
|
||
|
|
||
|
+ OCIO::LegacyViewingPipelineRcPtr vpt = OCIO::LegacyViewingPipeline::Create();
|
||
|
+
|
||
|
+ vpt->setDisplayViewTransform(transform);
|
||
|
+
|
||
|
/**
|
||
|
* Look support:
|
||
|
* As the OCIO docs will tell you, looks are a aesthetic transform that is
|
||
|
@@ -155,36 +146,37 @@ void OcioDisplayFilter::updateProcessor()
|
||
|
* override is all we can offer.
|
||
|
*/
|
||
|
if (config->getLook(look)) {
|
||
|
- transform->setLooksOverride(look);
|
||
|
- transform->setLooksOverrideEnabled(true);
|
||
|
+ vpt->setLooksOverride(look);
|
||
|
+ vpt->setLooksOverrideEnabled(true);
|
||
|
}
|
||
|
|
||
|
OCIO::GroupTransformRcPtr approximateTransform = OCIO::GroupTransform::Create();
|
||
|
|
||
|
// fstop exposure control -- not sure how that translates to our exposure
|
||
|
{
|
||
|
- float exposureGain = powf(2.0f, exposure);
|
||
|
+ const double exposureGain = pow(2.0, exposure);
|
||
|
|
||
|
- const qreal minRange = 0.001;
|
||
|
+ const double minRange = 0.001;
|
||
|
if (qAbs(blackPoint - whitePoint) < minRange) {
|
||
|
whitePoint = blackPoint + minRange;
|
||
|
}
|
||
|
|
||
|
- const float oldMin[] = { blackPoint, blackPoint, blackPoint, 0.0f };
|
||
|
- const float oldMax[] = { whitePoint, whitePoint, whitePoint, 1.0f };
|
||
|
+ const double oldMin[] = {blackPoint, blackPoint, blackPoint, 0.0};
|
||
|
+ const double oldMax[] = {whitePoint, whitePoint, whitePoint, 1.0};
|
||
|
|
||
|
- const float newMin[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||
|
- const float newMax[] = { exposureGain, exposureGain, exposureGain, 1.0f };
|
||
|
+ const double newMin[] = {0.0, 0.0, 0.0, 0.0};
|
||
|
+ const double newMax[] = {exposureGain, exposureGain, exposureGain, 1.0};
|
||
|
|
||
|
- float m44[16];
|
||
|
- float offset4[4];
|
||
|
+ double m44[16];
|
||
|
+ double offset4[4];
|
||
|
OCIO::MatrixTransform::Fit(m44, offset4, oldMin, oldMax, newMin, newMax);
|
||
|
- OCIO::MatrixTransformRcPtr mtx = OCIO::MatrixTransform::Create();
|
||
|
- mtx->setValue(m44, offset4);
|
||
|
- transform->setLinearCC(mtx);
|
||
|
+ OCIO::MatrixTransformRcPtr mtx = OCIO::MatrixTransform::Create();
|
||
|
+ mtx->setMatrix(m44);
|
||
|
+ mtx->setOffset(offset4);
|
||
|
+ vpt->setLinearCC(mtx);
|
||
|
|
||
|
// approximation (no color correction);
|
||
|
- approximateTransform->push_back(mtx);
|
||
|
+ approximateTransform->appendTransform(mtx);
|
||
|
}
|
||
|
|
||
|
// channel swizzle
|
||
|
@@ -226,32 +218,39 @@ void OcioDisplayFilter::updateProcessor()
|
||
|
channelHot[1] = 0;
|
||
|
channelHot[2] = 0;
|
||
|
channelHot[3] = 1;
|
||
|
- default:
|
||
|
- ;
|
||
|
+ default:;
|
||
|
}
|
||
|
- float lumacoef[3];
|
||
|
+ double lumacoef[3];
|
||
|
config->getDefaultLumaCoefs(lumacoef);
|
||
|
- float m44[16];
|
||
|
- float offset[4];
|
||
|
+ double m44[16];
|
||
|
+ double offset[4];
|
||
|
OCIO::MatrixTransform::View(m44, offset, channelHot, lumacoef);
|
||
|
OCIO::MatrixTransformRcPtr swizzleTransform = OCIO::MatrixTransform::Create();
|
||
|
- swizzleTransform->setValue(m44, offset);
|
||
|
- transform->setChannelView(swizzleTransform);
|
||
|
+ swizzleTransform->setMatrix(m44);
|
||
|
+ swizzleTransform->setOffset(offset);
|
||
|
+ vpt->setChannelView(swizzleTransform);
|
||
|
}
|
||
|
|
||
|
// Post-display transform gamma
|
||
|
{
|
||
|
- float exponent = 1.0f/std::max(1e-6f, static_cast<float>(gamma));
|
||
|
- const float exponent4f[] = { exponent, exponent, exponent, exponent };
|
||
|
- OCIO::ExponentTransformRcPtr expTransform = OCIO::ExponentTransform::Create();
|
||
|
+ double exponent = 1.0 / std::max(1e-6, gamma);
|
||
|
+ const double exponent4f[] = {exponent, exponent, exponent, exponent};
|
||
|
+ OCIO::ExponentTransformRcPtr expTransform = OCIO::ExponentTransform::Create();
|
||
|
expTransform->setValue(exponent4f);
|
||
|
- transform->setDisplayCC(expTransform);
|
||
|
+ vpt->setDisplayCC(expTransform);
|
||
|
|
||
|
// approximation (no color correction);
|
||
|
- approximateTransform->push_back(expTransform);
|
||
|
+ approximateTransform->appendTransform(expTransform);
|
||
|
}
|
||
|
|
||
|
- m_processor = config->getProcessor(transform);
|
||
|
+ try {
|
||
|
+ m_processor = vpt->getProcessor(config, config->getCurrentContext());
|
||
|
+ } catch (OCIO::Exception &e) {
|
||
|
+ // XXX: How to not break the OCIO shader now?
|
||
|
+ errKrita << "OCIO exception while parsing the current context:" << e.what();
|
||
|
+ m_shaderDirty = false;
|
||
|
+ return;
|
||
|
+ }
|
||
|
|
||
|
m_forwardApproximationProcessor = config->getProcessor(approximateTransform, OCIO::TRANSFORM_DIR_FORWARD);
|
||
|
|
||
|
@@ -259,7 +258,7 @@ void OcioDisplayFilter::updateProcessor()
|
||
|
m_revereseApproximationProcessor = config->getProcessor(approximateTransform, OCIO::TRANSFORM_DIR_INVERSE);
|
||
|
} catch (...) {
|
||
|
warnKrita << "OCIO inverted matrix does not exist!";
|
||
|
- //m_revereseApproximationProcessor;
|
||
|
+ // m_revereseApproximationProcessor;
|
||
|
}
|
||
|
|
||
|
m_shaderDirty = true;
|
||
|
@@ -272,16 +271,19 @@ bool OcioDisplayFilter::updateShader()
|
||
|
if (f) {
|
||
|
return updateShaderImpl(f);
|
||
|
}
|
||
|
+#if defined(QT_OPENGL_3)
|
||
|
} else if (KisOpenGL::hasOpenGL3()) {
|
||
|
QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
|
||
|
if (f) {
|
||
|
return updateShaderImpl(f);
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
// XXX This option can be removed once we move to Qt 5.7+
|
||
|
if (KisOpenGL::supportsLoD()) {
|
||
|
-#ifdef Q_OS_MAC
|
||
|
+#if defined(QT_OPENGL_3)
|
||
|
+#if defined(Q_OS_MAC) && defined(QT_OPENGL_3_2)
|
||
|
QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
|
||
|
#else
|
||
|
QOpenGLFunctions_3_0 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_0>();
|
||
|
@@ -289,23 +291,29 @@ bool OcioDisplayFilter::updateShader()
|
||
|
if (f) {
|
||
|
return updateShaderImpl(f);
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
- QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
|
||
|
+#if !defined(QT_OPENGL_ES_2)
|
||
|
+ QOpenGLFunctions_2_0 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_0>();
|
||
|
if (f) {
|
||
|
return updateShaderImpl(f);
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
-template <class F>
|
||
|
-bool OcioDisplayFilter::updateShaderImpl(F *f) {
|
||
|
+template<class F>
|
||
|
+bool OcioDisplayFilter::updateShaderImpl(F *f)
|
||
|
+{
|
||
|
// check whether we are allowed to use shaders -- though that should
|
||
|
// work for everyone these days
|
||
|
KisConfig cfg(true);
|
||
|
- if (!cfg.useOpenGL()) return false;
|
||
|
+ if (!cfg.useOpenGL())
|
||
|
+ return false;
|
||
|
|
||
|
- if (!m_shaderDirty) return false;
|
||
|
+ if (!m_shaderDirty)
|
||
|
+ return false;
|
||
|
|
||
|
if (!f) {
|
||
|
qWarning() << "Failed to get valid OpenGL functions for OcioDisplayFilter!";
|
||
|
@@ -316,71 +324,272 @@ bool OcioDisplayFilter::updateShaderImpl(F *f) {
|
||
|
|
||
|
bool shouldRecompileShader = false;
|
||
|
|
||
|
- const int lut3DEdgeSize = cfg.ocioLutEdgeSize();
|
||
|
+ // Step 1: Create a GPU Shader Description
|
||
|
+ OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc();
|
||
|
|
||
|
- if (m_lut3d.size() == 0) {
|
||
|
- //dbgKrita << "generating lut";
|
||
|
- f->glGenTextures(1, &m_lut3dTexID);
|
||
|
+#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
|
||
|
+ if (KisOpenGL::supportsLoD()) {
|
||
|
+ shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_3_0);
|
||
|
+ } else {
|
||
|
+ shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_1_0);
|
||
|
+ }
|
||
|
+#else
|
||
|
+ if (KisOpenGL::supportsLoD()) {
|
||
|
+ shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_3);
|
||
|
+ } else {
|
||
|
+ shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_2);
|
||
|
+ }
|
||
|
+#endif
|
||
|
|
||
|
- int num3Dentries = 3 * lut3DEdgeSize * lut3DEdgeSize * lut3DEdgeSize;
|
||
|
- m_lut3d.fill(0.0, num3Dentries);
|
||
|
+ shaderDesc->setFunctionName("OCIODisplay");
|
||
|
+ shaderDesc->setResourcePrefix("ocio_");
|
||
|
|
||
|
- f->glActiveTexture(GL_TEXTURE1);
|
||
|
- f->glBindTexture(GL_TEXTURE_3D, m_lut3dTexID);
|
||
|
+ // Step 2: Compute the 3D LUT
|
||
|
+#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
|
||
|
+ // ensure the new GPU pipeline is used with our GLES3 patch
|
||
|
+ // this way users won't run into errors when using Angle along with OCIO
|
||
|
+ const auto gpu = m_processor->getOptimizedGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_DEFAULT);
|
||
|
+#else
|
||
|
+ const int lut3DEdgeSize = cfg.ocioLutEdgeSize();
|
||
|
+ const auto gpu =
|
||
|
+ m_processor->getOptimizedLegacyGPUProcessor(OCIO::OptimizationFlags::OPTIMIZATION_DEFAULT, lut3DEdgeSize);
|
||
|
+#endif
|
||
|
|
||
|
- f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||
|
- f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
- f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||
|
- f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||
|
- f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||
|
- f->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
|
||
|
- lut3DEdgeSize, lut3DEdgeSize, lut3DEdgeSize,
|
||
|
- 0, GL_RGB, GL_FLOAT, &m_lut3d.constData()[0]);
|
||
|
+ gpu->extractGpuShaderInfo(shaderDesc);
|
||
|
+
|
||
|
+ // OCIO v2 assumes you'll use the OglApp helpers
|
||
|
+ // these are unusable from a Qt backend, because they rely on GLUT/GLFW
|
||
|
+ // ociodisplay original pipeline:
|
||
|
+ // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/508b3f4a0618435aeed2f45058208bdfa99e0887/src/apps/ociodisplay/main.cpp
|
||
|
+ // ociodisplay new pipeline is a single call:
|
||
|
+ // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/ffddc3341f5775c7866fe2c93275e1d5e0b0540f/src/apps/ociodisplay/main.cpp#L427
|
||
|
+ // we need to replicate this loop:
|
||
|
+ // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/dd59baf555656e09f52c3838e85ccf154497ec1d/src/libutils/oglapphelpers/oglapp.cpp#L191-L223
|
||
|
+ // calls functions from here:
|
||
|
+ // https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/dd59baf555656e09f52c3838e85ccf154497ec1d/src/libutils/oglapphelpers/glsl.cpp
|
||
|
+
|
||
|
+ for (const auto &tex : m_lut3dTexIDs) {
|
||
|
+ f->glDeleteTextures(1, &tex.m_uid);
|
||
|
}
|
||
|
|
||
|
- // Step 1: Create a GPU Shader Description
|
||
|
- OCIO::GpuShaderDesc shaderDesc;
|
||
|
+ m_lut3dTexIDs.clear();
|
||
|
|
||
|
- if (KisOpenGL::supportsLoD()) {
|
||
|
- shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_3);
|
||
|
- }
|
||
|
- else {
|
||
|
- shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
|
||
|
+ // This is the first available index for the textures.
|
||
|
+ unsigned currIndex = 1;
|
||
|
+
|
||
|
+ // Process the 3D LUT first.
|
||
|
+
|
||
|
+ const unsigned maxTexture3D = shaderDesc->getNum3DTextures();
|
||
|
+ for (unsigned idx = 0; idx < maxTexture3D; ++idx) {
|
||
|
+ // 1. Get the information of the 3D LUT.
|
||
|
+
|
||
|
+ const char *textureName = nullptr;
|
||
|
+ const char *samplerName = nullptr;
|
||
|
+ unsigned edgelen = 0;
|
||
|
+ OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
|
||
|
+ shaderDesc->get3DTexture(idx, textureName, samplerName, edgelen, interpolation);
|
||
|
+
|
||
|
+ if (!textureName || !*textureName || !samplerName || !*samplerName || edgelen == 0) {
|
||
|
+ errOpenGL << "The texture data is corrupted";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ const float *values = nullptr;
|
||
|
+ shaderDesc->get3DTextureValues(idx, values);
|
||
|
+ if (!values) {
|
||
|
+ errOpenGL << "The texture values are missing";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ // 2. Allocate the 3D LUT.
|
||
|
+
|
||
|
+ unsigned texId = 0;
|
||
|
+ {
|
||
|
+ if (values == nullptr) {
|
||
|
+ errOpenGL << "3D LUT" << idx << "Missing texture data";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ f->glGenTextures(1, &texId);
|
||
|
+
|
||
|
+ f->glActiveTexture(GL_TEXTURE0 + currIndex);
|
||
|
+
|
||
|
+ f->glBindTexture(GL_TEXTURE_3D, texId);
|
||
|
+
|
||
|
+ {
|
||
|
+ if (interpolation == OCIO::INTERP_NEAREST) {
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||
|
+ } else {
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
+ }
|
||
|
+
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||
|
+ }
|
||
|
+
|
||
|
+ f->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB32F_ARB, edgelen, edgelen, edgelen, 0, GL_RGB, GL_FLOAT, values);
|
||
|
+ }
|
||
|
+
|
||
|
+ // 3. Keep the texture id & name for the later enabling.
|
||
|
+
|
||
|
+ m_lut3dTexIDs.push_back({texId, textureName, samplerName, GL_TEXTURE_3D});
|
||
|
+
|
||
|
+ currIndex++;
|
||
|
}
|
||
|
|
||
|
+ // Process the 1D LUTs.
|
||
|
|
||
|
- shaderDesc.setFunctionName("OCIODisplay");
|
||
|
- shaderDesc.setLut3DEdgeLen(lut3DEdgeSize);
|
||
|
+ const unsigned maxTexture2D = shaderDesc->getNumTextures();
|
||
|
+ for (unsigned idx = 0; idx < maxTexture2D; ++idx) {
|
||
|
+ // 1. Get the information of the 1D LUT.
|
||
|
|
||
|
+ const char *textureName = nullptr;
|
||
|
+ const char *samplerName = nullptr;
|
||
|
+ unsigned width = 0;
|
||
|
+ unsigned height = 0;
|
||
|
+ OCIO::GpuShaderDesc::TextureType channel = OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL;
|
||
|
+ OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
|
||
|
+ shaderDesc->getTexture(idx, textureName, samplerName, width, height, channel, interpolation);
|
||
|
|
||
|
- // Step 2: Compute the 3D LUT
|
||
|
- QString lut3dCacheID = QString::fromLatin1(m_processor->getGpuLut3DCacheID(shaderDesc));
|
||
|
- if (lut3dCacheID != m_lut3dcacheid) {
|
||
|
- //dbgKrita << "Computing 3DLut " << m_lut3dcacheid;
|
||
|
- m_lut3dcacheid = lut3dCacheID;
|
||
|
- m_processor->getGpuLut3D(&m_lut3d[0], shaderDesc);
|
||
|
-
|
||
|
- f->glBindTexture(GL_TEXTURE_3D, m_lut3dTexID);
|
||
|
- f->glTexSubImage3D(GL_TEXTURE_3D, 0,
|
||
|
- 0, 0, 0,
|
||
|
- lut3DEdgeSize, lut3DEdgeSize, lut3DEdgeSize,
|
||
|
- GL_RGB, GL_FLOAT, &m_lut3d[0]);
|
||
|
+ if (!textureName || !*textureName || !samplerName || !*samplerName || width == 0) {
|
||
|
+ errOpenGL << "The texture data is corrupted";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ const float *values = nullptr;
|
||
|
+ shaderDesc->getTextureValues(idx, values);
|
||
|
+ if (!values) {
|
||
|
+ errOpenGL << "The texture values are missing";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ // 2. Allocate the 1D LUT (a 2D texture is needed to hold large LUTs).
|
||
|
+
|
||
|
+ unsigned texId = 0;
|
||
|
+ {
|
||
|
+ if (values == nullptr) {
|
||
|
+ errOpenGL << "1D LUT" << idx << "Missing texture data.";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ unsigned internalformat = GL_RGB32F_ARB;
|
||
|
+ unsigned format = GL_RGB;
|
||
|
+
|
||
|
+ if (channel == OCIO::GpuShaderCreator::TEXTURE_RED_CHANNEL) {
|
||
|
+ internalformat = GL_R32F;
|
||
|
+ format = GL_RED;
|
||
|
+ }
|
||
|
+
|
||
|
+ f->glGenTextures(1, &texId);
|
||
|
+
|
||
|
+ f->glActiveTexture(GL_TEXTURE0 + currIndex);
|
||
|
+
|
||
|
+#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
|
||
|
+#else
|
||
|
+ // 1D Textures are unsupported by OpenGL ES.
|
||
|
+ // https://github.com/AcademySoftwareFoundation/OpenColorIO/issues/1486
|
||
|
+ if (height > 1) {
|
||
|
+#endif
|
||
|
+ f->glBindTexture(GL_TEXTURE_2D, texId);
|
||
|
+
|
||
|
+ {
|
||
|
+ if (interpolation == OCIO::INTERP_NEAREST) {
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||
|
+ } else {
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
+ }
|
||
|
+
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||
|
+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||
|
+ }
|
||
|
+
|
||
|
+ f->glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, GL_FLOAT, values);
|
||
|
+#if OCIO_VERSION_HEX >= 0x2010100 || OCIO_VERSION_HEX >= 0x2020000
|
||
|
+#else
|
||
|
+ } else {
|
||
|
+ errOpenGL << "1D texture detected @" << idx << ", not supported by OpenGLES";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ // 3. Keep the texture id & name for the later enabling.
|
||
|
+
|
||
|
+ unsigned type = GL_TEXTURE_2D;
|
||
|
+ m_lut3dTexIDs.push_back({texId, textureName, samplerName, type});
|
||
|
+ currIndex++;
|
||
|
}
|
||
|
|
||
|
// Step 3: Generate the shader text
|
||
|
- QString shaderCacheID = QString::fromLatin1(m_processor->getGpuShaderTextCacheID(shaderDesc));
|
||
|
+ QString shaderCacheID = QString::fromLatin1(shaderDesc->getCacheID());
|
||
|
if (m_program.isEmpty() || shaderCacheID != m_shadercacheid) {
|
||
|
- //dbgKrita << "Computing Shader " << m_shadercacheid;
|
||
|
+ // dbgKrita << "Computing Shader " << m_shadercacheid;
|
||
|
|
||
|
m_shadercacheid = shaderCacheID;
|
||
|
|
||
|
- std::ostringstream os;
|
||
|
- os << m_processor->getGpuShaderText(shaderDesc) << "\n";
|
||
|
-
|
||
|
- m_program = QString::fromLatin1(os.str().c_str());
|
||
|
+ m_program = QString::fromLatin1("%1\n").arg(shaderDesc->getShaderText());
|
||
|
shouldRecompileShader = true;
|
||
|
}
|
||
|
|
||
|
+ // Step 4: mirror and bind uniforms
|
||
|
+ m_lut3dUniforms.clear();
|
||
|
+
|
||
|
+ const unsigned maxUniforms = shaderDesc->getNumUniforms();
|
||
|
+ for (unsigned idx = 0; idx < maxUniforms; ++idx) {
|
||
|
+ OCIO::GpuShaderDesc::UniformData data;
|
||
|
+ const char *name = shaderDesc->getUniform(idx, data);
|
||
|
+ if (data.m_type == OCIO::UNIFORM_UNKNOWN) {
|
||
|
+ errOpenGL << "Uniform" << idx << "has an unknown type";
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ // Transfer uniform.
|
||
|
+ m_lut3dUniforms.push_back({name, data});
|
||
|
+ }
|
||
|
+
|
||
|
m_shaderDirty = false;
|
||
|
return shouldRecompileShader;
|
||
|
}
|
||
|
+
|
||
|
+void OcioDisplayFilter::setupTextures(QOpenGLFunctions *f, QOpenGLShaderProgram *program) const
|
||
|
+{
|
||
|
+ for (unsigned int idx = 0; idx < m_lut3dTexIDs.size(); ++idx) {
|
||
|
+ const auto &data = m_lut3dTexIDs[idx];
|
||
|
+ f->glActiveTexture(GL_TEXTURE0 + 1 + idx);
|
||
|
+ f->glBindTexture(data.m_type, data.m_uid);
|
||
|
+ program->setUniformValue(program->uniformLocation(data.m_samplerName), GLint(1 + idx));
|
||
|
+ }
|
||
|
+
|
||
|
+ for (const KisTextureUniform &uniform : m_lut3dUniforms) {
|
||
|
+ const int m_handle = program->uniformLocation(uniform.m_name);
|
||
|
+
|
||
|
+ const OCIO::GpuShaderDesc::UniformData &m_data = uniform.m_data;
|
||
|
+
|
||
|
+ // Update value.
|
||
|
+ if (m_data.m_getDouble) {
|
||
|
+ program->setUniformValue(m_handle, static_cast<const GLfloat>(m_data.m_getDouble()));
|
||
|
+ } else if (m_data.m_getBool) {
|
||
|
+ program->setUniformValue(m_handle, static_cast<const GLfloat>(m_data.m_getBool() ? 1.0f : 0.0f));
|
||
|
+ } else if (m_data.m_getFloat3) {
|
||
|
+ program->setUniformValue(m_handle,
|
||
|
+ m_data.m_getFloat3()[0],
|
||
|
+ m_data.m_getFloat3()[1],
|
||
|
+ m_data.m_getFloat3()[2]);
|
||
|
+ } else if (m_data.m_vectorFloat.m_getSize && m_data.m_vectorFloat.m_getVector) {
|
||
|
+ program->setUniformValueArray(m_handle,
|
||
|
+ m_data.m_vectorFloat.m_getVector(),
|
||
|
+ m_data.m_vectorFloat.m_getSize(),
|
||
|
+ 1);
|
||
|
+ } else if (m_data.m_vectorInt.m_getSize && m_data.m_vectorInt.m_getVector) {
|
||
|
+ program->setUniformValueArray(m_handle, m_data.m_vectorInt.m_getVector(), m_data.m_vectorInt.m_getSize());
|
||
|
+ } else {
|
||
|
+ errOpenGL << "Uniform" << uniform.m_name << "is not linked to any value";
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/plugins/dockers/lut/ocio_display_filter.h b/plugins/dockers/lut/ocio_display_filter.h
|
||
|
index 48d896a4c0..963fcf5f93 100644
|
||
|
--- a/plugins/dockers/lut/ocio_display_filter.h
|
||
|
+++ b/plugins/dockers/lut/ocio_display_filter.h
|
||
|
@@ -1,38 +1,56 @@
|
||
|
/*
|
||
|
- * Copyright (c) 2012 Boudewijn Rempt <boud@valdyas.org>
|
||
|
+ * SPDX-FileCopyrightText: 2012 Boudewijn Rempt <boud@valdyas.org>
|
||
|
+ * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
|
||
|
*
|
||
|
- * 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 2 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, write to the Free Software
|
||
|
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
*/
|
||
|
+
|
||
|
#ifndef OCIO_DISPLAY_FILTER_H
|
||
|
#define OCIO_DISPLAY_FILTER_H
|
||
|
|
||
|
+#include <vector>
|
||
|
+
|
||
|
+#include <QOpenGLShaderProgram>
|
||
|
+
|
||
|
+#include <OpenColorIO.h>
|
||
|
+#include <OpenColorTransforms.h>
|
||
|
+#include <OpenColorTypes.h>
|
||
|
+
|
||
|
#include <kis_display_filter.h>
|
||
|
-#include <OpenColorIO/OpenColorIO.h>
|
||
|
-#include <OpenColorIO/OpenColorTransforms.h>
|
||
|
-#include <QVector>
|
||
|
-#include "kis_exposure_gamma_correction_interface.h"
|
||
|
+#include <kis_exposure_gamma_correction_interface.h>
|
||
|
|
||
|
namespace OCIO = OCIO_NAMESPACE;
|
||
|
|
||
|
-enum OCIO_CHANNEL_SWIZZLE {
|
||
|
- LUMINANCE,
|
||
|
- RGBA,
|
||
|
- R,
|
||
|
- G,
|
||
|
- B,
|
||
|
- A
|
||
|
+enum OCIO_CHANNEL_SWIZZLE { LUMINANCE, RGBA, R, G, B, A };
|
||
|
+
|
||
|
+struct KisTextureUniform {
|
||
|
+public:
|
||
|
+ KisTextureUniform(const QString &name, const OCIO::GpuShaderDesc::UniformData &data)
|
||
|
+ : m_name(name)
|
||
|
+ , m_data(data)
|
||
|
+ {
|
||
|
+ }
|
||
|
+
|
||
|
+ QString m_name;
|
||
|
+ OCIO::GpuShaderDesc::UniformData m_data;
|
||
|
+
|
||
|
+private:
|
||
|
+ KisTextureUniform() = delete;
|
||
|
+};
|
||
|
+
|
||
|
+struct KisTextureEntry {
|
||
|
+ unsigned m_uid = -1;
|
||
|
+ QString m_textureName;
|
||
|
+ QString m_samplerName;
|
||
|
+ unsigned m_type = -1;
|
||
|
+
|
||
|
+ KisTextureEntry(unsigned uid, const QString &textureName, const QString &samplerName, unsigned type)
|
||
|
+ : m_uid(uid)
|
||
|
+ , m_textureName(textureName)
|
||
|
+ , m_samplerName(samplerName)
|
||
|
+ , m_type(type)
|
||
|
+ {
|
||
|
+ }
|
||
|
};
|
||
|
|
||
|
class OcioDisplayFilter : public KisDisplayFilter
|
||
|
@@ -42,21 +60,23 @@ public:
|
||
|
explicit OcioDisplayFilter(KisExposureGammaCorrectionInterface *interface, QObject *parent = 0);
|
||
|
~OcioDisplayFilter();
|
||
|
|
||
|
- void filter(quint8 *pixels, quint32 numPixels);
|
||
|
- void approximateInverseTransformation(quint8 *pixels, quint32 numPixels);
|
||
|
- void approximateForwardTransformation(quint8 *pixels, quint32 numPixels);
|
||
|
- bool useInternalColorManagement() const;
|
||
|
- bool lockCurrentColorVisualRepresentation() const;
|
||
|
+ void filter(quint8 *pixels, quint32 numPixels) override;
|
||
|
+ void approximateInverseTransformation(quint8 *pixels, quint32 numPixels) override;
|
||
|
+ void approximateForwardTransformation(quint8 *pixels, quint32 numPixels) override;
|
||
|
+ bool useInternalColorManagement() const override;
|
||
|
+ bool lockCurrentColorVisualRepresentation() const override;
|
||
|
void setLockCurrentColorVisualRepresentation(bool value);
|
||
|
|
||
|
- bool updateShader();
|
||
|
- template <class F>
|
||
|
+ bool updateShader() override;
|
||
|
+
|
||
|
+ template<class F>
|
||
|
bool updateShaderImpl(F *f);
|
||
|
|
||
|
- KisExposureGammaCorrectionInterface *correctionInterface() const;
|
||
|
+ void setupTextures(QOpenGLFunctions *f, QOpenGLShaderProgram *program) const override;
|
||
|
|
||
|
- virtual QString program() const;
|
||
|
- GLuint lutTexture() const;
|
||
|
+ KisExposureGammaCorrectionInterface *correctionInterface() const override;
|
||
|
+
|
||
|
+ QString program() const override;
|
||
|
|
||
|
void updateProcessor();
|
||
|
|
||
|
@@ -67,14 +87,13 @@ public:
|
||
|
const char *view;
|
||
|
const char *look;
|
||
|
OCIO_CHANNEL_SWIZZLE swizzle;
|
||
|
- float exposure;
|
||
|
- float gamma;
|
||
|
- float blackPoint;
|
||
|
- float whitePoint;
|
||
|
+ double exposure;
|
||
|
+ double gamma;
|
||
|
+ double blackPoint;
|
||
|
+ double whitePoint;
|
||
|
bool forceInternalColorManagement;
|
||
|
|
||
|
private:
|
||
|
-
|
||
|
OCIO::ConstProcessorRcPtr m_processor;
|
||
|
OCIO::ConstProcessorRcPtr m_revereseApproximationProcessor;
|
||
|
OCIO::ConstProcessorRcPtr m_forwardApproximationProcessor;
|
||
|
@@ -84,10 +103,10 @@ private:
|
||
|
bool m_lockCurrentColorVisualRepresentation;
|
||
|
|
||
|
QString m_program;
|
||
|
- GLuint m_lut3dTexID;
|
||
|
- QVector<float> m_lut3d;
|
||
|
+ std::vector<KisTextureEntry> m_lut3dTexIDs;
|
||
|
QString m_lut3dcacheid;
|
||
|
QString m_shadercacheid;
|
||
|
+ std::vector<KisTextureUniform> m_lut3dUniforms;
|
||
|
|
||
|
bool m_shaderDirty;
|
||
|
};
|
||
|
diff --git a/plugins/dockers/lut/tests/CMakeLists.txt b/plugins/dockers/lut/tests/CMakeLists.txt
|
||
|
index 85cd5ecbc6..8891b8b683 100644
|
||
|
--- a/plugins/dockers/lut/tests/CMakeLists.txt
|
||
|
+++ b/plugins/dockers/lut/tests/CMakeLists.txt
|
||
|
@@ -11,5 +11,5 @@ krita_add_broken_unit_test(kis_ocio_display_filter_test.cpp
|
||
|
../ocio_display_filter.cpp
|
||
|
${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
|
||
|
TEST_NAME KisOcioDisplayFilterTest
|
||
|
- LINK_LIBRARIES kritaui ${OCIO_LIBRARIES} KF5::I18n Qt5::Test
|
||
|
+ LINK_LIBRARIES kritaui OpenColorIO::OpenColorIO KF5::I18n Qt5::Test
|
||
|
NAME_PREFIX "plugins-dockers-lut-")
|
||
|
diff --git a/plugins/dockers/lut/wdglut.ui b/plugins/dockers/lut/wdglut.ui
|
||
|
index 2ba3c2b073..403e5c26a3 100644
|
||
|
--- a/plugins/dockers/lut/wdglut.ui
|
||
|
+++ b/plugins/dockers/lut/wdglut.ui
|
||
|
@@ -7,7 +7,7 @@
|
||
|
<x>0</x>
|
||
|
<y>0</y>
|
||
|
<width>357</width>
|
||
|
- <height>286</height>
|
||
|
+ <height>328</height>
|
||
|
</rect>
|
||
|
</property>
|
||
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
|
||
|
@@ -338,7 +338,7 @@
|
||
|
</layout>
|
||
|
</item>
|
||
|
<item>
|
||
|
- <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,0">
|
||
|
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0">
|
||
|
<property name="spacing">
|
||
|
<number>2</number>
|
||
|
</property>
|
||
|
@@ -348,6 +348,13 @@
|
||
|
<property name="rightMargin">
|
||
|
<number>2</number>
|
||
|
</property>
|
||
|
+ <item>
|
||
|
+ <widget class="QLabel" name="m_lblOcioVersion">
|
||
|
+ <property name="text">
|
||
|
+ <string>TextLabel</string>
|
||
|
+ </property>
|
||
|
+ </widget>
|
||
|
+ </item>
|
||
|
<item>
|
||
|
<spacer name="horizontalSpacer">
|
||
|
<property name="orientation">
|
||
|
diff --git a/cmake/modules/FindOpenColorIO.cmake b/cmake/modules/FindOpenColorIO.cmake
|
||
|
new file mode 100644
|
||
|
index 0000000000..2a9e9310b1
|
||
|
--- /dev/null
|
||
|
+++ b/cmake/modules/FindOpenColorIO.cmake
|
||
|
@@ -0,0 +1,104 @@
|
||
|
+# Module to find OpenColorIO
|
||
|
+#
|
||
|
+# This module will first look into the directories hinted by the variables:
|
||
|
+# - OpenColorIO_ROOT
|
||
|
+#
|
||
|
+# This module defines the following variables:
|
||
|
+#
|
||
|
+# OPENCOLORIO_FOUND - True if OpenColorIO was found.
|
||
|
+# OPENCOLORIO_INCLUDES - where to find OpenColorIO.h
|
||
|
+# OPENCOLORIO_LIBRARIES - list of libraries to link against when using OpenColorIO
|
||
|
+# OPENCOLORIO_DEFINITIONS - Definitions needed when using OpenColorIO
|
||
|
+#
|
||
|
+# SPDX-FileCopyrightText: 2008 Contributors to the OpenImageIO project
|
||
|
+# SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
|
||
|
+# SPDX-License-Identifier: BSD-3-Clause
|
||
|
+
|
||
|
+include (FindPackageHandleStandardArgs)
|
||
|
+include (FindPackageMessage)
|
||
|
+
|
||
|
+find_path (OPENCOLORIO_INCLUDE_DIR
|
||
|
+ OpenColorIO.h
|
||
|
+ HINTS
|
||
|
+ ${OPENCOLORIO_INCLUDE_PATH}
|
||
|
+ ENV OPENCOLORIO_INCLUDE_PATH
|
||
|
+ PATHS
|
||
|
+ /sw/include
|
||
|
+ /opt/local/include
|
||
|
+ PATH_SUFFIXES OpenColorIO OpenColorIO1
|
||
|
+ DOC "The directory where OpenColorIO.h resides")
|
||
|
+
|
||
|
+if (EXISTS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorABI.h")
|
||
|
+ # Search twice, because this symbol changed between OCIO 1.x and 2.x
|
||
|
+ file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorABI.h" TMP
|
||
|
+ REGEX "^#define OCIO_VERSION_STR[ \t].*$")
|
||
|
+ if (NOT TMP)
|
||
|
+ file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorABI.h" TMP
|
||
|
+ REGEX "^#define OCIO_VERSION[ \t].*$")
|
||
|
+ endif ()
|
||
|
+ string (REGEX MATCHALL "([0-9]+)\\.([0-9]+)\\.[0-9]+" OPENCOLORIO_VERSION ${TMP})
|
||
|
+ set (OPENCOLORIO_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||
|
+ set (OPENCOLORIO_VERSION_MINOR ${CMAKE_MATCH_2})
|
||
|
+endif ()
|
||
|
+
|
||
|
+find_library (OPENCOLORIO_LIBRARY
|
||
|
+ NAMES
|
||
|
+ OpenColorIO
|
||
|
+ OpenColorIO_${OPENCOLORIO_VERSION_MAJOR}_${OPENCOLORIO_VERSION_MINOR}
|
||
|
+ OpenColorIO${OPENCOLORIO_VERSION_MAJOR}
|
||
|
+ HINTS
|
||
|
+ ${OPENCOLORIO_LIBRARY_PATH}
|
||
|
+ ENV OPENCOLORIO_LIBRARY_PATH
|
||
|
+ PATHS
|
||
|
+ /usr/lib64
|
||
|
+ /usr/local/lib64
|
||
|
+ /sw/lib
|
||
|
+ /opt/local/lib
|
||
|
+ DOC "The OCIO library")
|
||
|
+
|
||
|
+find_package_handle_standard_args (OpenColorIO
|
||
|
+ REQUIRED_VARS OPENCOLORIO_INCLUDE_DIR OPENCOLORIO_LIBRARY
|
||
|
+ FOUND_VAR OPENCOLORIO_FOUND
|
||
|
+ VERSION_VAR OPENCOLORIO_VERSION
|
||
|
+ )
|
||
|
+
|
||
|
+if (OpenColorIO_FOUND)
|
||
|
+ set (OPENCOLORIO_INCLUDES ${OPENCOLORIO_INCLUDE_DIR})
|
||
|
+ set (OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARY})
|
||
|
+ set (OPENCOLORIO_DEFINITIONS "")
|
||
|
+ if (NOT TARGET OpenColorIO::OpenColorIO)
|
||
|
+ add_library(OpenColorIO::OpenColorIO UNKNOWN IMPORTED)
|
||
|
+ set_target_properties(OpenColorIO::OpenColorIO PROPERTIES
|
||
|
+ INTERFACE_INCLUDE_DIRECTORIES "${OPENCOLORIO_INCLUDES}")
|
||
|
+
|
||
|
+ set_property(TARGET OpenColorIO::OpenColorIO APPEND PROPERTY
|
||
|
+ IMPORTED_LOCATION "${OPENCOLORIO_LIBRARIES}")
|
||
|
+ if (LINKSTATIC)
|
||
|
+ target_compile_definitions(OpenColorIO::OpenColorIO
|
||
|
+ INTERFACE "-DOpenColorIO_STATIC")
|
||
|
+ endif()
|
||
|
+ endif ()
|
||
|
+ if (NOT TARGET OpenColorIO::OpenColorIOHeaders)
|
||
|
+ add_library(OpenColorIO::OpenColorIOHeaders INTERFACE IMPORTED)
|
||
|
+ set_target_properties(OpenColorIO::OpenColorIOHeaders PROPERTIES
|
||
|
+ INTERFACE_INCLUDE_DIRECTORIES "${OPENCOLORIO_INCLUDES}")
|
||
|
+ endif ()
|
||
|
+endif ()
|
||
|
+
|
||
|
+if (OpenColorIO_FOUND AND LINKSTATIC)
|
||
|
+ # Is this necessary?
|
||
|
+ set (OPENCOLORIO_DEFINITIONS "-DOpenColorIO_STATIC")
|
||
|
+ find_library (TINYXML_LIBRARY NAMES tinyxml)
|
||
|
+ if (TINYXML_LIBRARY)
|
||
|
+ set (OPENCOLORIO_LIBRARIES "${OPENCOLORIO_LIBRARIES};${TINYXML_LIBRARY}" CACHE STRING "" FORCE)
|
||
|
+ endif ()
|
||
|
+ find_library (YAML_LIBRARY NAMES yaml-cpp)
|
||
|
+ if (YAML_LIBRARY)
|
||
|
+ set (OPENCOLORIO_LIBRARIES "${OPENCOLORIO_LIBRARIES};${YAML_LIBRARY}" CACHE STRING "" FORCE)
|
||
|
+ endif ()
|
||
|
+ find_library (LCMS2_LIBRARY NAMES lcms2)
|
||
|
+ if (LCMS2_LIBRARY)
|
||
|
+ set (OPENCOLORIO_LIBRARIES "${OPENCOLORIO_LIBRARIES};${LCMS2_LIBRARY}" CACHE STRING "" FORCE)
|
||
|
+ endif ()
|
||
|
+endif ()
|
||
|
+
|