Git commit 363dbb389ecdd4501b421fe4e550b6ea585b28b8 by L. E. Segovia. Committed on 07/10/2020 at 12:34. Pushed by lsegovia into branch 'krita/4.3'. LcmsColorSpace: demutex QColor transforms This commit replaces the shared buffer, transforms, and mutex with a stack-local buffer and two lockless stacks for fromQColor and toQColor. This also fixes transforms not being properly destroyed through cmsDeleteTransform. CCMAIL: kimageshop@kde.org R +0 -0 libs/global/kis_lockless_stack.h [from: libs/image/tiles3/ki= s_lockless_stack.h - 100% similarity] M +1 -1 libs/image/3rdparty/lock_free_map/qsbr.h M +1 -1 libs/image/kis_cached_paint_device.h M +1 -1 libs/image/kis_image.cc M +1 -1 libs/image/tiles3/tests/kis_lockless_stack_test.cpp M +59 -43 plugins/color/lcms2engine/LcmsColorSpace.h https://invent.kde.org/graphics/krita/commit/363dbb389ecdd4501b421fe4e550b6= ea585b28b8 diff --git a/libs/image/tiles3/kis_lockless_stack.h b/libs/global/kis_lockl= ess_stack.h similarity index 100% rename from libs/image/tiles3/kis_lockless_stack.h rename to libs/global/kis_lockless_stack.h diff --git a/libs/image/3rdparty/lock_free_map/qsbr.h b/libs/image/3rdparty= /lock_free_map/qsbr.h index 912f88227e..0c767a248b 100644 --- a/libs/image/3rdparty/lock_free_map/qsbr.h +++ b/libs/image/3rdparty/lock_free_map/qsbr.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include = #define CALL_MEMBER(obj, pmf) ((obj).*(pmf)) = diff --git a/libs/image/kis_cached_paint_device.h b/libs/image/kis_cached_p= aint_device.h index 2cbde7e427..760e7491a1 100644 --- a/libs/image/kis_cached_paint_device.h +++ b/libs/image/kis_cached_paint_device.h @@ -19,7 +19,7 @@ #ifndef __KIS_CACHED_PAINT_DEVICE_H #define __KIS_CACHED_PAINT_DEVICE_H = -#include "tiles3/kis_lockless_stack.h" +#include "kis_lockless_stack.h" #include "kis_paint_device.h" #include "kis_selection.h" = diff --git a/libs/image/kis_image.cc b/libs/image/kis_image.cc index 1352e0612c..433237ed72 100644 --- a/libs/image/kis_image.cc +++ b/libs/image/kis_image.cc @@ -97,7 +97,7 @@ #include "kis_layer_projection_plane.h" = #include "kis_update_time_monitor.h" -#include "tiles3/kis_lockless_stack.h" +#include "kis_lockless_stack.h" = #include = diff --git a/libs/image/tiles3/tests/kis_lockless_stack_test.cpp b/libs/ima= ge/tiles3/tests/kis_lockless_stack_test.cpp index 91f35828fc..ac35a334ab 100644 --- a/libs/image/tiles3/tests/kis_lockless_stack_test.cpp +++ b/libs/image/tiles3/tests/kis_lockless_stack_test.cpp @@ -21,7 +21,7 @@ = #include "kis_debug.h" = -#include "tiles3/kis_lockless_stack.h" +#include "kis_lockless_stack.h" #include "config-limit-long-tests.h" = void KisLocklessStackTest::testOperations() diff --git a/plugins/color/lcms2engine/LcmsColorSpace.h b/plugins/color/lcm= s2engine/LcmsColorSpace.h index 749a00ea31..de5b048047 100644 --- a/plugins/color/lcms2engine/LcmsColorSpace.h +++ b/plugins/color/lcms2engine/LcmsColorSpace.h @@ -2,6 +2,7 @@ * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005-2006 C. Boemann * Copyright (c) 2004,2006-2007 Cyrille Berger + * Copyright (c) 2020 L. E. Segovia * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,11 +23,10 @@ #ifndef KOLCMSCOLORSPACE_H_ #define KOLCMSCOLORSPACE_H_ = -#include +#include #include -#include -#include = +#include "colorprofiles/LcmsColorProfileContainer.h" #include "kis_assert.h" = = @@ -156,16 +156,29 @@ class LcmsColorSpace : public KoColorSpaceAbstract<_C= STraits>, public KoLcmsInfo cmsHTRANSFORM cmsAlphaTransform; }; = + struct KisLcmsLastTransformation { + cmsHPROFILE profile =3D nullptr; // Last used profile to trans= form to/from RGB + cmsHTRANSFORM transform =3D nullptr; // Last used transform to/fro= m RGB + + ~KisLcmsLastTransformation() + { + if (transform) + cmsDeleteTransform(transform); + } + }; + + typedef QSharedPointer KisLcmsLastTransform= ationSP; + + typedef KisLocklessStack KisLcmsTransform= ationStack; + struct Private { - mutable quint8 *qcolordata; // A small buffer for conversion from = and to qcolor. KoLcmsDefaultTransformations *defaultTransformations; = - mutable cmsHPROFILE lastRGBProfile; // Last used profile to tra= nsform to/from RGB - mutable cmsHTRANSFORM lastToRGB; // Last used transform to t= ransform to RGB - mutable cmsHTRANSFORM lastFromRGB; // Last used transform to t= ransform from RGB + KisLcmsTransformationStack fromRGBCachedTransformations; // Last u= sed transforms + KisLcmsTransformationStack toRGBCachedTransformations; // Last u= sed transforms + LcmsColorProfileContainer *profile; KoColorProfile *colorProfile; - QMutex mutex; }; = protected: @@ -184,27 +197,18 @@ protected: d->profile =3D asLcmsProfile(p); Q_ASSERT(d->profile); d->colorProfile =3D p; - d->qcolordata =3D 0; - d->lastRGBProfile =3D 0; - d->lastToRGB =3D 0; - d->lastFromRGB =3D 0; d->defaultTransformations =3D 0; } = ~LcmsColorSpace() override { delete d->colorProfile; - delete[] d->qcolordata; delete d->defaultTransformations; delete d; } = void init() { - // Default pixel buffer for QColor conversion - d->qcolordata =3D new quint8[3]; - Q_CHECK_PTR(d->qcolordata); - KIS_ASSERT(d->profile); = if (KoLcmsDefaultTransformations::s_RGBProfile =3D=3D 0) { @@ -252,54 +256,66 @@ public: = void fromQColor(const QColor &color, quint8 *dst, const KoColorProfile= *koprofile =3D 0) const override { - QMutexLocker locker(&d->mutex); - d->qcolordata[2] =3D color.red(); - d->qcolordata[1] =3D color.green(); - d->qcolordata[0] =3D color.blue(); + std::array qcolordata; + + qcolordata[2] =3D static_cast(color.red()); + qcolordata[1] =3D static_cast(color.green()); + qcolordata[0] =3D static_cast(color.blue()); = LcmsColorProfileContainer *profile =3D asLcmsProfile(koprofile); if (profile =3D=3D 0) { // Default sRGB KIS_ASSERT(d->defaultTransformations && d->defaultTransformati= ons->fromRGB); = - cmsDoTransform(d->defaultTransformations->fromRGB, d->qcolorda= ta, dst, 1); + cmsDoTransform(d->defaultTransformations->fromRGB, qcolordata.= data(), dst, 1); } else { - if (d->lastFromRGB =3D=3D 0 || (d->lastFromRGB !=3D 0 && d->la= stRGBProfile !=3D profile->lcmsProfile())) { - d->lastFromRGB =3D cmsCreateTransform(profile->lcmsProfile= (), - TYPE_BGR_8, - d->profile->lcmsProfil= e(), - this->colorSpaceType(), - KoColorConversionTrans= formation::internalRenderingIntent(), - KoColorConversionTrans= formation::internalConversionFlags()); - d->lastRGBProfile =3D profile->lcmsProfile(); + KisLcmsLastTransformationSP last; + while (d->fromRGBCachedTransformations.pop(last) && last->tran= sform && last->profile !=3D profile->lcmsProfile()) { + last.reset(); + } = + if (!last) { + last.reset(new KisLcmsLastTransformation()); + last->transform =3D cmsCreateTransform( + profile->lcmsProfile(), TYPE_BGR_8, d->profile->lcmsPr= ofile(), this->colorSpaceType(), KoColorConversionTransformation::internalR= enderingIntent(), KoColorConversionTransformation::internalConversionFlags(= )); + last->profile =3D profile->lcmsProfile(); } - KIS_ASSERT(d->lastFromRGB); - cmsDoTransform(d->lastFromRGB, d->qcolordata, dst, 1); + + KIS_ASSERT(last->transform); + cmsDoTransform(last->transform, qcolordata.data(), dst, 1); + d->fromRGBCachedTransformations.push(last); } = - this->setOpacity(dst, (quint8)(color.alpha()), 1); + this->setOpacity(dst, static_cast(color.alpha()), 1); } = void toQColor(const quint8 *src, QColor *c, const KoColorProfile *kopr= ofile =3D 0) const override { - QMutexLocker locker(&d->mutex); + std::array qcolordata; + LcmsColorProfileContainer *profile =3D asLcmsProfile(koprofile); if (profile =3D=3D 0) { // Default sRGB transform Q_ASSERT(d->defaultTransformations && d->defaultTransformation= s->toRGB); - cmsDoTransform(d->defaultTransformations->toRGB, const_cast (src), d->qcolordata, 1); + cmsDoTransform(d->defaultTransformations->toRGB, src, qcolorda= ta.data(), 1); } else { - if (d->lastToRGB =3D=3D 0 || (d->lastToRGB !=3D 0 && d->lastRG= BProfile !=3D profile->lcmsProfile())) { - d->lastToRGB =3D cmsCreateTransform(d->profile->lcmsProfil= e(), this->colorSpaceType(), - profile->lcmsProfile(), = TYPE_BGR_8, - KoColorConversionTransfo= rmation::internalRenderingIntent(), - KoColorConversionTransfo= rmation::internalConversionFlags()); - d->lastRGBProfile =3D profile->lcmsProfile(); + KisLcmsLastTransformationSP last; + while (d->toRGBCachedTransformations.pop(last) && last->transf= orm && last->profile !=3D profile->lcmsProfile()) { + last.reset(); + } + + if (!last) { + last.reset(new KisLcmsLastTransformation()); + last->transform =3D cmsCreateTransform( + d->profile->lcmsProfile(), this->colorSpaceType(), pro= file->lcmsProfile(), TYPE_BGR_8, KoColorConversionTransformation::internalR= enderingIntent(), KoColorConversionTransformation::internalConversionFlags(= )); + last->profile =3D profile->lcmsProfile(); } - cmsDoTransform(d->lastToRGB, const_cast (src), d->qc= olordata, 1); + + KIS_ASSERT(last->transform); + cmsDoTransform(last->transform, src, qcolordata.data(), 1); + d->toRGBCachedTransformations.push(last); } - c->setRgb(d->qcolordata[2], d->qcolordata[1], d->qcolordata[0]); + c->setRgb(qcolordata[2], qcolordata[1], qcolordata[0]); c->setAlpha(this->opacityU8(src)); } =20