autotests: test that ColorPipeline and OpenGL shader results at least somewhat match

(cherry picked from commit 47af438ace)
wilder/Plasma/6.2
Xaver Hugl 1 year ago
parent d2f176afbc
commit cef793da62
  1. 81
      autotests/test_colorspaces.cpp

@ -4,10 +4,16 @@
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include <QImage>
#include <QTest>
#include "core/colorpipeline.h"
#include "core/colorspace.h"
#include "opengl/eglcontext.h"
#include "opengl/egldisplay.h"
#include "opengl/glframebuffer.h"
#include "opengl/glshader.h"
#include "opengl/glshadermanager.h"
using namespace KWin;
@ -27,6 +33,8 @@ private Q_SLOTS:
void testColorPipeline_data();
void testColorPipeline();
void testXYZ();
void testOpenglShader_data();
void testOpenglShader();
};
static bool compareVectors(const QVector3D &one, const QVector3D &two, float maxDifference)
@ -211,6 +219,79 @@ void TestColorspaces::testXYZ()
QVERIFY(isFuzzyIdentity(xyz.fromXYZ()));
}
void TestColorspaces::testOpenglShader_data()
{
QTest::addColumn<RenderingIntent>("intent");
QTest::addColumn<double>("maxError");
// the allowed error here needs to be this high because of llvmpipe. With real GPU drivers it's lower
QTest::addRow("Perceptual") << RenderingIntent::Perceptual << 6.5;
QTest::addRow("RelativeColorimetric") << RenderingIntent::RelativeColorimetric << 1.5;
QTest::addRow("AbsoluteColorimetric") << RenderingIntent::AbsoluteColorimetric << 1.5;
QTest::addRow("RelativeColorimetricWithBPC") << RenderingIntent::RelativeColorimetricWithBPC << 1.5;
}
void TestColorspaces::testOpenglShader()
{
QFETCH(RenderingIntent, intent);
QFETCH(double, maxError);
const auto display = EglDisplay::create(eglGetDisplay(EGL_DEFAULT_DISPLAY));
const auto context = EglContext::create(display.get(), EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT);
const ColorDescription src(NamedColorimetry::BT709, TransferFunction(TransferFunction::linear, 0, 400), 100, 0, 200, 400);
const ColorDescription dst(NamedColorimetry::BT709, TransferFunction(TransferFunction::gamma22), 100, 0, 100, 100);
QImage input(255, 255, QImage::Format_RGBA8888_Premultiplied);
for (int x = 0; x < input.width(); x++) {
for (int y = 0; y < input.height(); y++) {
input.setPixel(x, y, qRgba(x, y, 0, 255));
}
}
QImage openGlResult;
{
ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace);
QMatrix4x4 proj;
proj.ortho(QRectF(0, 0, input.width(), input.height()));
binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, proj);
binder.shader()->setColorspaceUniforms(src, dst, intent);
const auto target = GLTexture::allocate(GL_RGBA8, input.size());
GLFramebuffer buffer(target.get());
context->pushFramebuffer(&buffer);
const auto srcColor = GLTexture::upload(input);
srcColor->render(input.size());
context->popFramebuffer();
openGlResult = target->toImage();
openGlResult.mirror();
}
QImage pipelineResult(input.width(), input.height(), QImage::Format_RGBA8888_Premultiplied);
{
const auto pipeline = ColorPipeline::create(src, dst, intent);
for (int x = 0; x < input.width(); x++) {
for (int y = 0; y < input.height(); y++) {
const auto pixel = input.pixel(x, y);
const QVector3D colors = QVector3D(qRed(pixel), qGreen(pixel), qBlue(pixel)) / 255;
const QVector3D output = pipeline.evaluate(colors) * 255;
pipelineResult.setPixel(x, y, qRgba(std::round(output.x()), std::round(output.y()), std::round(output.z()), 255));
}
}
}
for (int x = 0; x < input.width(); x++) {
for (int y = 0; y < input.height(); y++) {
const auto glPixel = openGlResult.pixel(x, y);
const QVector3D glColors = QVector3D(qRed(glPixel), qGreen(glPixel), qBlue(glPixel));
const auto pipePixel = pipelineResult.pixel(x, y);
const QVector3D pipeColors = QVector3D(qRed(pipePixel), qGreen(pipePixel), qBlue(pipePixel));
const QVector3D difference = (glColors - pipeColors);
QCOMPARE_LE(difference.length(), maxError);
}
}
}
QTEST_MAIN(TestColorspaces)
#include "test_colorspaces.moc"

Loading…
Cancel
Save