[gimp/pippin/linear-is-the-new-black: 1/11] app: make layer modes more configurable



commit fa5c0e7f6ca105093810808e9d757538a947bcf1
Author: Øyvind Kolås <pippin gimp org>
Date:   Sun Jan 15 21:11:00 2017 +0100

    app: make layer modes more configurable
    
    Implement a common utility function gimp_blend_composite that uses utility
    functions for implementing layer modes, with separate (possibly SIMD) optimized
    loops for blending and compositing, with configured linear TRC, perceptual
    gamma TRC or even using CIE Lab as the space.

 .../gimpoperationadditionlegacy.c                  |   40 +-
 .../gimpoperationadditionlegacy.h                  |   19 +-
 .../layer-modes-legacy/gimpoperationburnlegacy.c   |   23 +-
 .../layer-modes-legacy/gimpoperationburnlegacy.h   |   19 +-
 .../gimpoperationdarkenonlylegacy.c                |   21 +-
 .../gimpoperationdarkenonlylegacy.h                |   19 +-
 .../gimpoperationdifferencelegacy.c                |   23 +-
 .../gimpoperationdifferencelegacy.h                |   19 +-
 .../layer-modes-legacy/gimpoperationdividelegacy.c |   23 +-
 .../layer-modes-legacy/gimpoperationdividelegacy.h |   19 +-
 .../layer-modes-legacy/gimpoperationdodgelegacy.c  |   23 +-
 .../layer-modes-legacy/gimpoperationdodgelegacy.h  |   19 +-
 .../gimpoperationgrainextractlegacy.c              |   37 +-
 .../gimpoperationgrainextractlegacy.h              |   19 +-
 .../gimpoperationgrainmergelegacy.c                |   37 +-
 .../gimpoperationgrainmergelegacy.h                |    5 +-
 .../gimpoperationhardlightlegacy.c                 |   23 +-
 .../gimpoperationhardlightlegacy.h                 |    5 +-
 .../gimpoperationhsvcolorlegacy.c                  |   23 +-
 .../gimpoperationhsvcolorlegacy.h                  |    5 +-
 .../layer-modes-legacy/gimpoperationhsvhuelegacy.c |   23 +-
 .../layer-modes-legacy/gimpoperationhsvhuelegacy.h |   20 +-
 .../gimpoperationhsvsaturationlegacy.c             |   23 +-
 .../gimpoperationhsvsaturationlegacy.h             |   19 +-
 .../gimpoperationhsvvaluelegacy.c                  |   23 +-
 .../gimpoperationhsvvaluelegacy.h                  |   19 +-
 .../gimpoperationlightenonlylegacy.c               |   23 +-
 .../gimpoperationlightenonlylegacy.h               |   19 +-
 .../gimpoperationmultiplylegacy.c                  |   23 +-
 .../gimpoperationmultiplylegacy.h                  |   20 +-
 .../layer-modes-legacy/gimpoperationscreenlegacy.c |   21 +-
 .../layer-modes-legacy/gimpoperationscreenlegacy.h |   19 +-
 .../gimpoperationsoftlightlegacy.c                 |   24 +-
 .../gimpoperationsoftlightlegacy.h                 |   19 +-
 .../gimpoperationsubtractlegacy.c                  |   37 +-
 .../gimpoperationsubtractlegacy.h                  |   19 +-
 app/operations/layer-modes/Makefile.am             |    1 +
 app/operations/layer-modes/gimpblendcomposite.h    |  912 ++++++++++++++++++++
 app/operations/layer-modes/gimpoperationaddition.c |   73 +--
 app/operations/layer-modes/gimpoperationaddition.h |   19 +-
 .../layer-modes/gimpoperationantierase.c           |   23 +-
 .../layer-modes/gimpoperationantierase.h           |   19 +-
 app/operations/layer-modes/gimpoperationbehind.c   |   26 +-
 app/operations/layer-modes/gimpoperationbehind.h   |   19 +-
 app/operations/layer-modes/gimpoperationburn.c     |   79 +--
 app/operations/layer-modes/gimpoperationburn.h     |   19 +-
 .../layer-modes/gimpoperationcolorerase.c          |   23 +-
 .../layer-modes/gimpoperationcolorerase.h          |   19 +-
 .../layer-modes/gimpoperationdarkenonly.c          |   67 +--
 .../layer-modes/gimpoperationdarkenonly.h          |   19 +-
 .../layer-modes/gimpoperationdifference.c          |   68 +--
 .../layer-modes/gimpoperationdifference.h          |    5 +-
 app/operations/layer-modes/gimpoperationdissolve.c |   23 +-
 app/operations/layer-modes/gimpoperationdissolve.h |   19 +-
 app/operations/layer-modes/gimpoperationdivide.c   |   72 +--
 app/operations/layer-modes/gimpoperationdivide.h   |   19 +-
 app/operations/layer-modes/gimpoperationdodge.c    |   69 +--
 app/operations/layer-modes/gimpoperationdodge.h    |   19 +-
 app/operations/layer-modes/gimpoperationerase.c    |   23 +-
 app/operations/layer-modes/gimpoperationerase.h    |   19 +-
 .../layer-modes/gimpoperationgrainextract.c        |   83 +--
 .../layer-modes/gimpoperationgrainextract.h        |   19 +-
 .../layer-modes/gimpoperationgrainmerge.c          |   68 +--
 .../layer-modes/gimpoperationgrainmerge.h          |   19 +-
 .../layer-modes/gimpoperationhardlight.c           |   81 +--
 .../layer-modes/gimpoperationhardlight.h           |   19 +-
 app/operations/layer-modes/gimpoperationhsvcolor.c |   80 +--
 app/operations/layer-modes/gimpoperationhsvcolor.h |   19 +-
 app/operations/layer-modes/gimpoperationhsvhue.c   |   85 +--
 app/operations/layer-modes/gimpoperationhsvhue.h   |   19 +-
 .../layer-modes/gimpoperationhsvsaturation.c       |   80 +--
 .../layer-modes/gimpoperationhsvsaturation.h       |   19 +-
 app/operations/layer-modes/gimpoperationhsvvalue.c |   68 +--
 app/operations/layer-modes/gimpoperationhsvvalue.h |   19 +-
 .../layer-modes/gimpoperationlchchroma.c           |   66 +-
 .../layer-modes/gimpoperationlchchroma.h           |   24 +-
 app/operations/layer-modes/gimpoperationlchcolor.c |   71 +-
 app/operations/layer-modes/gimpoperationlchcolor.h |   38 +-
 app/operations/layer-modes/gimpoperationlchhue.c   |   68 +-
 app/operations/layer-modes/gimpoperationlchhue.h   |   39 +-
 .../layer-modes/gimpoperationlchlightness.c        |   77 +-
 .../layer-modes/gimpoperationlchlightness.h        |   38 +-
 .../layer-modes/gimpoperationlightenonly.c         |   81 +--
 .../layer-modes/gimpoperationlightenonly.h         |   19 +-
 app/operations/layer-modes/gimpoperationmultiply.c |   66 +--
 app/operations/layer-modes/gimpoperationmultiply.h |   19 +-
 .../layer-modes/gimpoperationnormal-sse2.c         |   23 +-
 .../layer-modes/gimpoperationnormal-sse4.c         |   23 +-
 app/operations/layer-modes/gimpoperationnormal.c   |   24 +-
 app/operations/layer-modes/gimpoperationnormal.h   |   61 +-
 app/operations/layer-modes/gimpoperationoverlay.c  |   76 +--
 app/operations/layer-modes/gimpoperationoverlay.h  |   19 +-
 .../layer-modes/gimpoperationpointlayermode.c      |   18 +-
 .../layer-modes/gimpoperationpointlayermode.h      |   47 +-
 app/operations/layer-modes/gimpoperationreplace.c  |   23 +-
 app/operations/layer-modes/gimpoperationreplace.h  |   19 +-
 app/operations/layer-modes/gimpoperationscreen.c   |   70 +--
 app/operations/layer-modes/gimpoperationscreen.h   |   19 +-
 .../layer-modes/gimpoperationsoftlight.c           |   96 +--
 .../layer-modes/gimpoperationsoftlight.h           |   20 +-
 app/operations/layer-modes/gimpoperationsubtract.c |   67 +--
 app/operations/layer-modes/gimpoperationsubtract.h |   19 +-
 app/operations/operations-types.h                  |   19 +-
 app/paint/gimppaintcore-loops.c                    |    8 +-
 104 files changed, 2375 insertions(+), 1986 deletions(-)
---
diff --git a/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.c
index 0fcb0a7..a72c45d 100644
--- a/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.c
@@ -66,28 +66,34 @@ gimp_operation_addition_legacy_init (GimpOperationAdditionLegacy *self)
 
 static gboolean
 gimp_operation_addition_legacy_process (GeglOperation       *operation,
-                                      void                *in_buf,
-                                      void                *aux_buf,
-                                      void                *aux2_buf,
-                                      void                *out_buf,
-                                      glong                samples,
-                                      const GeglRectangle *roi,
-                                      gint                 level)
+                                        void                *in_buf,
+                                        void                *aux_buf,
+                                        void                *aux2_buf,
+                                        void                *out_buf,
+                                        glong                samples,
+                                        const GeglRectangle *roi,
+                                        gint                 level)
 {
-  gfloat opacity  = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_addition_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_addition_legacy_process_pixels (in_buf, aux_buf,
+                  aux2_buf, out_buf, layer_mode->opacity, samples, roi, level,
+                  layer_mode->blend_trc, layer_mode->composite_trc, 
+                  layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_addition_legacy_process_pixels (gfloat              *in,
-                                               gfloat              *layer,
-                                               gfloat              *mask,
-                                               gfloat              *out,
-                                               gfloat               opacity,
-                                               glong                samples,
-                                               const GeglRectangle *roi,
-                                               gint                 level)
+gimp_operation_addition_legacy_process_pixels (gfloat                *in,
+                                               gfloat                *layer,
+                                               gfloat                *mask,
+                                               gfloat                *out,
+                                               gfloat                 opacity,
+                                               glong                  samples,
+                                               const GeglRectangle   *roi,
+                                               gint                   level,
+                                               GimpLayerBlendTRC      blend_trc,
+                                               GimpLayerBlendTRC      composite_trc,
+                                               GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.h
index c070005..644644a 100644
--- a/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationadditionlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationAdditionLegacyClass
 
 GType    gimp_operation_addition_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_addition_legacy_process_pixels (gfloat              *in,
-                                                        gfloat              *layer,
-                                                        gfloat              *mask,
-                                                        gfloat              *out,
-                                                        gfloat               opacity,
-                                                        glong                samples,
-                                                        const GeglRectangle *roi,
-                                                        gint                 level);
+gboolean gimp_operation_addition_legacy_process_pixels (gfloat                *in,
+                                                        gfloat                *layer,
+                                                        gfloat                *mask,
+                                                        gfloat                *out,
+                                                        gfloat                 opacity,
+                                                        glong                  samples,
+                                                        const GeglRectangle   *roi,
+                                                        gint                   level,
+                                                        GimpLayerBlendTRC      blend_trc, 
+                                                        GimpLayerBlendTRC      composite_trc,
+                                                        GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_ADDITION_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationburnlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationburnlegacy.c
index d5dc65f..1ed5d50 100644
--- a/app/operations/layer-modes-legacy/gimpoperationburnlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationburnlegacy.c
@@ -74,20 +74,23 @@ gimp_operation_burn_legacy_process (GeglOperation       *operation,
                                     const GeglRectangle *roi,
                                     gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_burn_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_burn_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_burn_legacy_process_pixels (gfloat              *in,
-                                           gfloat              *layer,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_burn_legacy_process_pixels (gfloat                *in,
+                                           gfloat                *layer,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationburnlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationburnlegacy.h
index d967f40..dc5dd4f 100644
--- a/app/operations/layer-modes-legacy/gimpoperationburnlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationburnlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationBurnLegacyClass
 
 GType    gimp_operation_burn_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_burn_legacy_process_pixels (gfloat              *in,
-                                                    gfloat              *layer,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
+gboolean gimp_operation_burn_legacy_process_pixels (gfloat                *in,
+                                                    gfloat                *layer,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_BURN_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.c
index bd56644..764b039 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.c
@@ -74,20 +74,23 @@ gimp_operation_darken_only_legacy_process (GeglOperation       *operation,
                                            const GeglRectangle *roi,
                                            gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_darken_only_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_darken_only_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
 gimp_operation_darken_only_legacy_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level)
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc,
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.h
index 331e84f..3ce85b2 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationdarkenonlylegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationDarkenOnlyLegacyClass
 
 GType    gimp_operation_darken_only_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_darken_only_legacy_process_pixels (gfloat              *in,
-                                                           gfloat              *layer,
-                                                           gfloat              *mask,
-                                                           gfloat              *out,
-                                                           gfloat               opacity,
-                                                           glong                samples,
-                                                           const GeglRectangle *roi,
-                                                           gint                 level);
+gboolean gimp_operation_darken_only_legacy_process_pixels (gfloat                *in,
+                                                           gfloat                *layer,
+                                                           gfloat                *mask,
+                                                           gfloat                *out,
+                                                           gfloat                 opacity,
+                                                           glong                  samples,
+                                                           const GeglRectangle   *roi,
+                                                           gint                   level,
+                                                           GimpLayerBlendTRC      blend_trc, 
+                                                           GimpLayerBlendTRC      composite_trc,
+                                                           GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DARKEN_ONLY_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.c
index 0fcb6d0..36143fa 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.c
@@ -74,20 +74,23 @@ gimp_operation_difference_legacy_process (GeglOperation       *operation,
                                           const GeglRectangle *roi,
                                           gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_difference_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_difference_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_difference_legacy_process_pixels (gfloat              *in,
-                                                 gfloat              *layer,
-                                                 gfloat              *mask,
-                                                 gfloat              *out,
-                                                 gfloat               opacity,
-                                                 glong                samples,
-                                                 const GeglRectangle *roi,
-                                                 gint                 level)
+gimp_operation_difference_legacy_process_pixels (gfloat                *in,
+                                                 gfloat                *layer,
+                                                 gfloat                *mask,
+                                                 gfloat                *out,
+                                                 gfloat                 opacity,
+                                                 glong                  samples,
+                                                 const GeglRectangle   *roi,
+                                                 gint                   level,
+                                                 GimpLayerBlendTRC      blend_trc,
+                                                 GimpLayerBlendTRC      composite_trc,
+                                                 GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.h
index 50e1434..bb2e118 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationdifferencelegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationDifferenceLegacyClass
 
 GType    gimp_operation_difference_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_difference_legacy_process_pixels (gfloat              *in,
-                                                          gfloat              *layer,
-                                                          gfloat              *mask,
-                                                          gfloat              *out,
-                                                          gfloat               opacity,
-                                                          glong                samples,
-                                                          const GeglRectangle *roi,
-                                                          gint                 level);
+gboolean gimp_operation_difference_legacy_process_pixels (gfloat                *in,
+                                                          gfloat                *layer,
+                                                          gfloat                *mask,
+                                                          gfloat                *out,
+                                                          gfloat                 opacity,
+                                                          glong                  samples,
+                                                          const GeglRectangle   *roi,
+                                                          gint                   level,
+                                                          GimpLayerBlendTRC      blend_trc, 
+                                                          GimpLayerBlendTRC      composite_trc,
+                                                          GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DIFFERENCE_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationdividelegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationdividelegacy.c
index 50bfac7..e82a901 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdividelegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationdividelegacy.c
@@ -74,20 +74,23 @@ gimp_operation_divide_legacy_process (GeglOperation       *operation,
                                       const GeglRectangle *roi,
                                       gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_divide_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_divide_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_divide_legacy_process_pixels (gfloat              *in,
-                                             gfloat              *layer,
-                                             gfloat              *mask,
-                                             gfloat              *out,
-                                             gfloat               opacity,
-                                             glong                samples,
-                                             const GeglRectangle *roi,
-                                             gint                 level)
+gimp_operation_divide_legacy_process_pixels (gfloat                *in,
+                                             gfloat                *layer,
+                                             gfloat                *mask,
+                                             gfloat                *out,
+                                             gfloat                 opacity,
+                                             glong                  samples,
+                                             const GeglRectangle   *roi,
+                                             gint                   level,
+                                             GimpLayerBlendTRC      blend_trc,
+                                             GimpLayerBlendTRC      composite_trc,
+                                             GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationdividelegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationdividelegacy.h
index 5b6a6c2..f2f4dd6 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdividelegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationdividelegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationDivideLegacyClass
 
 GType    gimp_operation_divide_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_divide_legacy_process_pixels (gfloat              *in,
-                                                      gfloat              *layer,
-                                                      gfloat              *mask,
-                                                      gfloat              *out,
-                                                      gfloat               opacity,
-                                                      glong                samples,
-                                                      const GeglRectangle *roi,
-                                                      gint                 level);
+gboolean gimp_operation_divide_legacy_process_pixels (gfloat                *in,
+                                                      gfloat                *layer,
+                                                      gfloat                *mask,
+                                                      gfloat                *out,
+                                                      gfloat                 opacity,
+                                                      glong                  samples,
+                                                      const GeglRectangle   *roi,
+                                                      gint                   level,
+                                                      GimpLayerBlendTRC      blend_trc, 
+                                                      GimpLayerBlendTRC      composite_trc,
+                                                      GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DIVIDE_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.c
index 966aabf..024ecb6 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.c
@@ -74,20 +74,23 @@ gimp_operation_dodge_legacy_process (GeglOperation       *operation,
                                      const GeglRectangle *roi,
                                      gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_dodge_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_dodge_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_dodge_legacy_process_pixels (gfloat              *in,
-                                            gfloat              *layer,
-                                            gfloat              *mask,
-                                            gfloat              *out,
-                                            gfloat               opacity,
-                                            glong                samples,
-                                            const GeglRectangle *roi,
-                                            gint                 level)
+gimp_operation_dodge_legacy_process_pixels (gfloat                *in,
+                                            gfloat                *layer,
+                                            gfloat                *mask,
+                                            gfloat                *out,
+                                            gfloat                 opacity,
+                                            glong                  samples,
+                                            const GeglRectangle   *roi,
+                                            gint                   level,
+                                            GimpLayerBlendTRC      blend_trc,
+                                            GimpLayerBlendTRC      composite_trc,
+                                            GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.h
index 73d09f4..e29edd7 100644
--- a/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationdodgelegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationDodgeLegacyClass
 
 GType    gimp_operation_dodge_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_dodge_legacy_process_pixels (gfloat              *in,
-                                                     gfloat              *layer,
-                                                     gfloat              *mask,
-                                                     gfloat              *out,
-                                                     gfloat               opacity,
-                                                     glong                samples,
-                                                     const GeglRectangle *roi,
-                                                     gint                 level);
+gboolean gimp_operation_dodge_legacy_process_pixels (gfloat                *in,
+                                                     gfloat                *layer,
+                                                     gfloat                *mask,
+                                                     gfloat                *out,
+                                                     gfloat                 opacity,
+                                                     glong                  samples,
+                                                     const GeglRectangle   *roi,
+                                                     gint                   level,
+                                                     GimpLayerBlendTRC      blend_trc, 
+                                                     GimpLayerBlendTRC      composite_trc,
+                                                     GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DODGE_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c
index 1ee14de..7c02900 100644
--- a/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c
@@ -29,13 +29,13 @@
 
 
 static gboolean gimp_operation_grain_extract_legacy_process (GeglOperation       *operation,
-                                                           void                *in_buf,
-                                                           void                *aux_buf,
-                                                           void                *aux2_buf,
-                                                           void                *out_buf,
-                                                           glong                samples,
-                                                           const GeglRectangle *roi,
-                                                           gint                 level);
+                                                             void                *in_buf,
+                                                             void                *aux_buf,
+                                                             void                *aux2_buf,
+                                                             void                *out_buf,
+                                                             glong                samples,
+                                                             const GeglRectangle *roi,
+                                                             gint                 level);
 
 
 G_DEFINE_TYPE (GimpOperationGrainExtractLegacy, gimp_operation_grain_extract_legacy,
@@ -74,20 +74,23 @@ gimp_operation_grain_extract_legacy_process (GeglOperation       *operation,
                                              const GeglRectangle *roi,
                                              gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_grain_extract_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_grain_extract_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_grain_extract_legacy_process_pixels (gfloat              *in,
-                                                    gfloat              *layer,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level)
+gimp_operation_grain_extract_legacy_process_pixels (gfloat                *in,
+                                                    gfloat                *layer,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc,
+                                                    GimpLayerBlendTRC      composite_Trc,
+                                                    GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.h
index 28306e5..e1d91d2 100644
--- a/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationGrainExtractLegacyClass
 
 GType    gimp_operation_grain_extract_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_grain_extract_legacy_process_pixels (gfloat              *in,
-                                                             gfloat              *layer,
-                                                             gfloat              *mask,
-                                                             gfloat              *out,
-                                                             gfloat               opacity,
-                                                             glong                samples,
-                                                             const GeglRectangle *roi,
-                                                             gint                 level);
+gboolean gimp_operation_grain_extract_legacy_process_pixels (gfloat                *in,
+                                                             gfloat                *layer,
+                                                             gfloat                *mask,
+                                                             gfloat                *out,
+                                                             gfloat                 opacity,
+                                                             glong                  samples,
+                                                             const GeglRectangle   *roi,
+                                                             gint                   level,
+                                                             GimpLayerBlendTRC      blend_trc, 
+                                                             GimpLayerBlendTRC      composite_trc,
+                                                             GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_GRAIN_EXTRACT_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c
index 9ee1690..2534f5d 100644
--- a/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c
@@ -29,13 +29,13 @@
 
 
 static gboolean gimp_operation_grain_merge_legacy_process (GeglOperation       *operation,
-                                                         void                *in_buf,
-                                                         void                *aux_buf,
-                                                         void                *aux2_buf,
-                                                         void                *out_buf,
-                                                         glong                samples,
-                                                         const GeglRectangle *roi,
-                                                         gint                 level);
+                                                           void                *in_buf,
+                                                           void                *aux_buf,
+                                                           void                *aux2_buf,
+                                                           void                *out_buf,
+                                                           glong                samples,
+                                                           const GeglRectangle *roi,
+                                                           gint                 level);
 
 
 G_DEFINE_TYPE (GimpOperationGrainMergeLegacy, gimp_operation_grain_merge_legacy,
@@ -74,20 +74,23 @@ gimp_operation_grain_merge_legacy_process (GeglOperation       *operation,
                                            const GeglRectangle *roi,
                                            gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_grain_merge_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_grain_merge_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_grain_merge_legacy_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level)
+gimp_operation_grain_merge_legacy_process_pixels (gfloat                *in,
+                                                  gfloat                *layer,
+                                                  gfloat                *mask,
+                                                  gfloat                *out,
+                                                  gfloat                 opacity,
+                                                  glong                  samples,
+                                                  const GeglRectangle   *roi,
+                                                  gint                   level,
+                                                  GimpLayerBlendTRC      blend_trc,
+                                                  GimpLayerBlendTRC      composite_trc,
+                                                  GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.h
index 789098a..4f4db94 100644
--- a/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.h
@@ -56,7 +56,10 @@ gboolean gimp_operation_grain_merge_legacy_process_pixels (gfloat              *
                                                            gfloat               opacity,
                                                            glong                samples,
                                                            const GeglRectangle *roi,
-                                                           gint                 level);
+                                                           gint                 level,
+                                                           GimpLayerBlendTRC    blend_trc, 
+                                                           GimpLayerBlendTRC    composite_trc,
+                                                           GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_GRAIN_MERGE_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c
index 826bca6..6b7dc4c 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c
@@ -74,20 +74,23 @@ gimp_operation_hardlight_legacy_process (GeglOperation       *operation,
                                          const GeglRectangle *roi,
                                          gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hardlight_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_hardlight_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hardlight_legacy_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level)
+gimp_operation_hardlight_legacy_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc,
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.h
index bbc4894..a704750 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.h
@@ -56,7 +56,10 @@ gboolean gimp_operation_hardlight_legacy_process_pixels (gfloat              *in
                                                          gfloat               opacity,
                                                          glong                samples,
                                                          const GeglRectangle *roi,
-                                                         gint                 level);
+                                                         gint                 level,
+                                                         GimpLayerBlendTRC    blend_trc, 
+                                                         GimpLayerBlendTRC    composite_trc,
+                                                         GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HARDLIGHT_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.c
index 43e2ec4..b653132 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.c
@@ -78,20 +78,23 @@ gimp_operation_hsv_color_legacy_process (GeglOperation       *operation,
                                          const GeglRectangle *roi,
                                          gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hsv_color_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_hsv_color_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_color_legacy_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level)
+gimp_operation_hsv_color_legacy_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc,
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.h
index 67edae4..268654c 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvcolorlegacy.h
@@ -56,7 +56,10 @@ gboolean gimp_operation_hsv_color_legacy_process_pixels (gfloat              *in
                                                          gfloat               opacity,
                                                          glong                samples,
                                                          const GeglRectangle *roi,
-                                                         gint                 level);
+                                                         gint                 level,
+                                                         GimpLayerBlendTRC    blend_trc, 
+                                                         GimpLayerBlendTRC    composite_trc,
+                                                         GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_COLOR_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.c
index b7c2897..5cd4cbd 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.c
@@ -78,20 +78,23 @@ gimp_operation_hsv_hue_legacy_process (GeglOperation       *operation,
                                        const GeglRectangle *roi,
                                        gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hsv_hue_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_hsv_hue_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_hue_legacy_process_pixels (gfloat              *in,
-                                              gfloat              *layer,
-                                              gfloat              *mask,
-                                              gfloat              *out,
-                                              gfloat               opacity,
-                                              glong                samples,
-                                              const GeglRectangle *roi,
-                                              gint                 level)
+gimp_operation_hsv_hue_legacy_process_pixels (gfloat                *in,
+                                              gfloat                *layer,
+                                              gfloat                *mask,
+                                              gfloat                *out,
+                                              gfloat                 opacity,
+                                              glong                  samples,
+                                              const GeglRectangle   *roi,
+                                              gint                   level,
+                                              GimpLayerBlendTRC      blend_trc,
+                                              GimpLayerBlendTRC      composite_trc,
+                                              GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.h
index 3316c15..44dbd7e 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvhuelegacy.h
@@ -49,14 +49,18 @@ struct _GimpOperationHsvHueLegacyClass
 
 GType    gimp_operation_hsv_hue_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_hue_legacy_process_pixels (gfloat              *in,
-                                                       gfloat              *layer,
-                                                       gfloat              *mask,
-                                                       gfloat              *out,
-                                                       gfloat               opacity,
-                                                       glong                samples,
-                                                       const GeglRectangle *roi,
-                                                       gint                 level);
+gboolean gimp_operation_hsv_hue_legacy_process_pixels (gfloat                *in,
+                                                       gfloat                *layer,
+                                                       gfloat                *mask,
+                                                       gfloat                *out,
+                                                       gfloat                 opacity,
+                                                       glong                  samples,
+                                                       const GeglRectangle   *roi,
+                                                       gint                   level,
+                                                       GimpLayerBlendTRC      blend_trc, 
+                                                       GimpLayerBlendTRC      composite_trc,
+                                                       GimpLayerCompositeMode composite_mode);
+
 
 
 #endif /* __GIMP_OPERATION_HSV_HUE_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.c
index 5be8b2a..42ebe11 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.c
@@ -78,20 +78,23 @@ gimp_operation_hsv_saturation_legacy_process (GeglOperation       *operation,
                                               const GeglRectangle *roi,
                                               gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hsv_saturation_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_hsv_saturation_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_saturation_legacy_process_pixels (gfloat              *in,
-                                                     gfloat              *layer,
-                                                     gfloat              *mask,
-                                                     gfloat              *out,
-                                                     gfloat               opacity,
-                                                     glong                samples,
-                                                     const GeglRectangle *roi,
-                                                     gint                 level)
+gimp_operation_hsv_saturation_legacy_process_pixels (gfloat                *in,
+                                                     gfloat                *layer,
+                                                     gfloat                *mask,
+                                                     gfloat                *out,
+                                                     gfloat                 opacity,
+                                                     glong                  samples,
+                                                     const GeglRectangle   *roi,
+                                                     gint                   level,
+                                                     GimpLayerBlendTRC      blend_trc,
+                                                     GimpLayerBlendTRC      composite_trc,
+                                                     GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.h
index acfc343..e4f9c6a 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvsaturationlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationHsvSaturationLegacyClass
 
 GType    gimp_operation_hsv_saturation_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_saturation_legacy_process_pixels (gfloat              *in,
-                                                              gfloat              *layer,
-                                                              gfloat              *mask,
-                                                              gfloat              *out,
-                                                              gfloat               opacity,
-                                                              glong                samples,
-                                                              const GeglRectangle *roi,
-                                                              gint                 level);
+gboolean gimp_operation_hsv_saturation_legacy_process_pixels (gfloat                *in,
+                                                              gfloat                *layer,
+                                                              gfloat                *mask,
+                                                              gfloat                *out,
+                                                              gfloat                 opacity,
+                                                              glong                  samples,
+                                                              const GeglRectangle   *roi,
+                                                              gint                   level,
+                                                              GimpLayerBlendTRC      blend_trc, 
+                                                              GimpLayerBlendTRC      composite_trc,
+                                                              GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_SATURATION_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.c
index c75681d..6424b11 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.c
@@ -78,20 +78,23 @@ gimp_operation_hsv_value_legacy_process (GeglOperation       *operation,
                                          const GeglRectangle *roi,
                                          gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hsv_value_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_hsv_value_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_value_legacy_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level)
+gimp_operation_hsv_value_legacy_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc,
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.h
index 8d88a9c..721362a 100644
--- a/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationhsvvaluelegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationHsvValueLegacyClass
 
 GType    gimp_operation_hsv_value_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_value_legacy_process_pixels (gfloat              *in,
-                                                         gfloat              *layer,
-                                                         gfloat              *mask,
-                                                         gfloat              *out,
-                                                         gfloat               opacity,
-                                                         glong                samples,
-                                                         const GeglRectangle *roi,
-                                                         gint                 level);
+gboolean gimp_operation_hsv_value_legacy_process_pixels (gfloat                *in,
+                                                         gfloat                *layer,
+                                                         gfloat                *mask,
+                                                         gfloat                *out,
+                                                         gfloat                 opacity,
+                                                         glong                  samples,
+                                                         const GeglRectangle   *roi,
+                                                         gint                   level,
+                                                         GimpLayerBlendTRC      blend_trc, 
+                                                         GimpLayerBlendTRC      composite_trc,
+                                                         GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_VALUE_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.c
index b84814c..628c924 100644
--- a/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.c
@@ -74,20 +74,23 @@ gimp_operation_lighten_only_legacy_process (GeglOperation       *operation,
                                             const GeglRectangle *roi,
                                             gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_lighten_only_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_lighten_only_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_lighten_only_legacy_process_pixels (gfloat              *in,
-                                                   gfloat              *layer,
-                                                   gfloat              *mask,
-                                                   gfloat              *out,
-                                                   gfloat               opacity,
-                                                   glong                samples,
-                                                   const GeglRectangle *roi,
-                                                   gint                 level)
+gimp_operation_lighten_only_legacy_process_pixels (gfloat                *in,
+                                                   gfloat                *layer,
+                                                   gfloat                *mask,
+                                                   gfloat                *out,
+                                                   gfloat                 opacity,
+                                                   glong                  samples,
+                                                   const GeglRectangle   *roi,
+                                                   gint                   level,
+                                                   GimpLayerBlendTRC      blend_trc,
+                                                   GimpLayerBlendTRC      composite_trc,
+                                                   GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.h
index 4d93515..d37636c 100644
--- a/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationlightenonlylegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationLightenOnlyLegacyClass
 
 GType    gimp_operation_lighten_only_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_lighten_only_legacy_process_pixels (gfloat              *in,
-                                                            gfloat              *layer,
-                                                            gfloat              *mask,
-                                                            gfloat              *out,
-                                                            gfloat               opacity,
-                                                            glong                samples,
-                                                            const GeglRectangle *roi,
-                                                            gint                 level);
+gboolean gimp_operation_lighten_only_legacy_process_pixels (gfloat                *in,
+                                                            gfloat                *layer,
+                                                            gfloat                *mask,
+                                                            gfloat                *out,
+                                                            gfloat                 opacity,
+                                                            glong                  samples,
+                                                            const GeglRectangle   *roi,
+                                                            gint                   level,
+                                                            GimpLayerBlendTRC      blend_trc, 
+                                                            GimpLayerBlendTRC      composite_trc,
+                                                            GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_LIGHTEN_ONLY_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.c
index 280c844..bdfed8b 100644
--- a/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.c
@@ -74,20 +74,23 @@ gimp_operation_multiply_legacy_process (GeglOperation       *operation,
                                         const GeglRectangle *roi,
                                         gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_multiply_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_multiply_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_multiply_legacy_process_pixels (gfloat              *in,
-                                               gfloat              *layer,
-                                               gfloat              *mask,
-                                               gfloat              *out,
-                                               gfloat               opacity,
-                                               glong                samples,
-                                               const GeglRectangle *roi,
-                                               gint                 level)
+gimp_operation_multiply_legacy_process_pixels (gfloat                *in,
+                                               gfloat                *layer,
+                                               gfloat                *mask,
+                                               gfloat                *out,
+                                               gfloat                 opacity,
+                                               glong                  samples,
+                                               const GeglRectangle   *roi,
+                                               gint                   level,
+                                               GimpLayerBlendTRC      blend_trc,
+                                               GimpLayerBlendTRC      composite_trc,
+                                               GimpLayerCompositeMode composite_mode)
 {
   const gboolean  has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.h
index 20b8c83..299e280 100644
--- a/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationmultiplylegacy.h
@@ -49,14 +49,16 @@ struct _GimpOperationMultiplyLegacyClass
 
 GType    gimp_operation_multiply_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_multiply_legacy_process_pixels (gfloat              *in,
-                                                        gfloat              *layer,
-                                                        gfloat              *mask,
-                                                        gfloat              *out,
-                                                        gfloat               opacity,
-                                                        glong                samples,
-                                                        const GeglRectangle *roi,
-                                                        gint                 level);
-
+gboolean gimp_operation_multiply_legacy_process_pixels (gfloat                *in,
+                                                        gfloat                *layer,
+                                                        gfloat                *mask,
+                                                        gfloat                *out,
+                                                        gfloat                 opacity,
+                                                        glong                  samples,
+                                                        const GeglRectangle   *roi,
+                                                        gint                   level,
+                                                        GimpLayerBlendTRC      blend_trc, 
+                                                        GimpLayerBlendTRC      composite_trc,
+                                                        GimpLayerCompositeMode composite_mode);
 
 #endif /* __GIMP_OPERATION_MULTIPLY_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.c
index b7ab4f4..9023c9a 100644
--- a/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.c
@@ -74,20 +74,23 @@ gimp_operation_screen_legacy_process (GeglOperation       *operation,
                                       const GeglRectangle *roi,
                                       gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_screen_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_screen_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
 gimp_operation_screen_legacy_process_pixels (gfloat              *in,
-                                           gfloat              *layer,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+                                           gfloat                *layer,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
   const gboolean  has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.h
index 6d80e0d..319d10f 100644
--- a/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationscreenlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationScreenLegacyClass
 
 GType    gimp_operation_screen_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_screen_legacy_process_pixels (gfloat              *in,
-                                                      gfloat              *layer,
-                                                      gfloat              *mask,
-                                                      gfloat              *out,
-                                                      gfloat               opacity,
-                                                      glong                samples,
-                                                      const GeglRectangle *roi,
-                                                      gint                 level);
+gboolean gimp_operation_screen_legacy_process_pixels (gfloat                *in,
+                                                      gfloat                *layer,
+                                                      gfloat                *mask,
+                                                      gfloat                *out,
+                                                      gfloat                 opacity,
+                                                      glong                  samples,
+                                                      const GeglRectangle   *roi,
+                                                      gint                   level,
+                                                      GimpLayerBlendTRC      blend_trc, 
+                                                      GimpLayerBlendTRC      composite_trc,
+                                                      GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_SCREEN_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c
index ee1e4ed..47e522b 100644
--- a/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c
@@ -92,20 +92,22 @@ gimp_operation_softlight_legacy_process (GeglOperation       *operation,
                                        const GeglRectangle *roi,
                                        gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_softlight_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_softlight_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_softlight_legacy_process_pixels (gfloat              *in,
-                                              gfloat              *layer,
-                                              gfloat              *mask,
-                                              gfloat              *out,
-                                              gfloat               opacity,
-                                              glong                samples,
-                                              const GeglRectangle *roi,
-                                              gint                 level)
+gimp_operation_softlight_legacy_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc,
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.h
index a9f76e2..5ea11b0 100644
--- a/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationSoftlightLegacyClass
 
 GType    gimp_operation_softlight_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_softlight_legacy_process_pixels (gfloat              *in,
-                                                         gfloat              *layer,
-                                                         gfloat              *mask,
-                                                         gfloat              *out,
-                                                         gfloat               opacity,
-                                                         glong                samples,
-                                                         const GeglRectangle *roi,
-                                                         gint                 level);
+gboolean gimp_operation_softlight_legacy_process_pixels (gfloat                *in,
+                                                         gfloat                *layer,
+                                                         gfloat                *mask,
+                                                         gfloat                *out,
+                                                         gfloat                 opacity,
+                                                         glong                  samples,
+                                                         const GeglRectangle   *roi,
+                                                         gint                   level,
+                                                         GimpLayerBlendTRC      blend_trc, 
+                                                         GimpLayerBlendTRC      composite_trc,
+                                                         GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_SOFTLIGHT_LEGACY_H__ */
diff --git a/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.c
index 504956a..7c6e237 100644
--- a/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.c
+++ b/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.c
@@ -66,28 +66,31 @@ gimp_operation_subtract_legacy_init (GimpOperationSubtractLegacy *self)
 
 static gboolean
 gimp_operation_subtract_legacy_process (GeglOperation       *operation,
-                                      void                *in_buf,
-                                      void                *aux_buf,
-                                      void                *aux2_buf,
-                                      void                *out_buf,
-                                      glong                samples,
-                                      const GeglRectangle *roi,
-                                      gint                 level)
+                                        void                *in_buf,
+                                        void                *aux_buf,
+                                        void                *aux2_buf,
+                                        void                *out_buf,
+                                        glong                samples,
+                                        const GeglRectangle *roi,
+                                        gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_subtract_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_subtract_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_subtract_legacy_process_pixels (gfloat              *in,
-                                             gfloat              *layer,
-                                             gfloat              *mask,
-                                             gfloat              *out,
-                                             gfloat               opacity,
-                                             glong                samples,
-                                             const GeglRectangle *roi,
-                                             gint                 level)
+gimp_operation_subtract_legacy_process_pixels (gfloat                *in,
+                                               gfloat                *layer,
+                                               gfloat                *mask,
+                                               gfloat                *out,
+                                               gfloat                 opacity,
+                                               glong                  samples,
+                                               const GeglRectangle   *roi,
+                                               gint                   level,
+                                               GimpLayerBlendTRC      blend_trc,
+                                               GimpLayerBlendTRC      composite_trc,
+                                               GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.h 
b/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.h
index 45c6582..59299ca 100644
--- a/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.h
+++ b/app/operations/layer-modes-legacy/gimpoperationsubtractlegacy.h
@@ -49,14 +49,17 @@ struct _GimpOperationSubtractLegacyClass
 
 GType    gimp_operation_subtract_legacy_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_subtract_legacy_process_pixels (gfloat              *in,
-                                                        gfloat              *layer,
-                                                        gfloat              *mask,
-                                                        gfloat              *out,
-                                                        gfloat               opacity,
-                                                        glong                samples,
-                                                        const GeglRectangle *roi,
-                                                        gint                 level);
+gboolean gimp_operation_subtract_legacy_process_pixels (gfloat                *in,
+                                                        gfloat                *layer,
+                                                        gfloat                *mask,
+                                                        gfloat                *out,
+                                                        gfloat                 opacity,
+                                                        glong                  samples,
+                                                        const GeglRectangle   *roi,
+                                                        gint                   level,
+                                                        GimpLayerBlendTRC      blend_trc, 
+                                                        GimpLayerBlendTRC      composite_trc,
+                                                        GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_SUBTRACT_LEGACY_H__ */
diff --git a/app/operations/layer-modes/Makefile.am b/app/operations/layer-modes/Makefile.am
index 55c3c3f..2f4d531 100644
--- a/app/operations/layer-modes/Makefile.am
+++ b/app/operations/layer-modes/Makefile.am
@@ -22,6 +22,7 @@ libapplayermodes_generic_a_sources = \
        gimpoperationpointlayermode.h   \
        gimplayermodefunctions.c        \
        gimplayermodefunctions.h        \
+       gimpblendcomposite.h            \
        \
        gimpoperationaddition.c         \
        gimpoperationaddition.h         \
diff --git a/app/operations/layer-modes/gimpblendcomposite.h b/app/operations/layer-modes/gimpblendcomposite.h
new file mode 100644
index 0000000..8ae3b10
--- /dev/null
+++ b/app/operations/layer-modes/gimpblendcomposite.h
@@ -0,0 +1,912 @@
+/* GIMP - The GNU Image Manipulation Program
+ * gimpblendcomposite
+ * Copyright (C) 2017 Øyvind Kolås <pippin gimp org>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BLEND_COMPOSITE_H__
+#define __GIMP_BLEND_COMPOSITE_H__
+
+
+#include <gegl-plugin.h>
+#include <math.h>
+#include <alloca.h>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "../operations-enums.h"
+#include "../operations-types.h"
+#include "libgimpcolor/gimpcolor.h"
+extern const Babl *_gimp_fish_rgba_to_perceptual;
+extern const Babl *_gimp_fish_perceptual_to_rgba;
+extern const Babl *_gimp_fish_perceptual_to_laba;
+extern const Babl *_gimp_fish_rgba_to_laba;
+extern const Babl *_gimp_fish_laba_to_rgba;
+extern const Babl *_gimp_fish_laba_to_perceptual;
+
+static inline void
+compfun_src_atop (gfloat *in,
+                  gfloat *layer,
+                  gfloat *mask,
+                  gfloat  opacity,
+                  gfloat *out,
+                  gint    samples)
+{
+  while (samples--)
+    {
+      gfloat comp_alpha = layer[ALPHA] * opacity;
+      if (mask)
+        comp_alpha *= *mask;
+ 
+      if (comp_alpha == 0.0f)
+        {
+          out[RED]   = in[RED];
+          out[GREEN] = in[GREEN];
+          out[BLUE]  = in[BLUE];
+        }
+        else
+        {
+          gint   b;
+          for (b = RED; b < ALPHA; b++)
+            out[b] = layer[b] * comp_alpha + in[b] * (1.0f - comp_alpha);
+        }
+      out[ALPHA] = in[ALPHA];
+ 
+      in    += 4;
+      out   += 4;
+      layer += 4;
+ 
+      if (mask)
+        mask++;
+    }
+}
+
+static inline void
+compfun_src_over (gfloat *in,
+                  gfloat *layer,
+                  gfloat *mask,
+                  gfloat *out,
+                  gfloat  opacity,
+                  gint    samples)
+{
+  while (samples--)
+    {
+      gfloat new_alpha;
+      gfloat comp_alpha = layer[ALPHA] * opacity;
+      if (mask)
+        comp_alpha *= *mask;
+ 
+      new_alpha = comp_alpha + (1.0f - comp_alpha) * in[ALPHA];
+ 
+      if (comp_alpha == 0.0f || new_alpha == 0.0f)
+        {
+          out[RED]   = in[RED];
+          out[GREEN] = in[GREEN];
+          out[BLUE]  = in[BLUE];
+        }
+        else
+        {
+          gint   b;
+          gfloat ratio = comp_alpha / new_alpha;
+          for (b = RED; b < ALPHA; b++)
+            out[b] = layer[b] * ratio + in[b] * (1.0f - ratio);
+        }
+ 
+      out[ALPHA] = new_alpha;
+ 
+      in    += 4;
+      layer += 4;
+      out   += 4;
+ 
+      if (mask)
+        mask++;
+    }
+}
+
+
+static inline void
+compfun_src_in (gfloat *in,
+                gfloat *layer,
+                gfloat *mask,
+                gfloat  opacity,
+                gfloat *out,
+                gint    samples)
+{
+  while (samples--)
+    {
+      gfloat new_alpha = in[ALPHA] * layer[ALPHA] * opacity;
+      if (mask)
+        new_alpha *= *mask;
+ 
+      if (new_alpha == 0.0f)
+        {
+          out[RED]   = in[RED];
+          out[GREEN] = in[GREEN];
+          out[BLUE]  = in[BLUE];
+        }
+      else
+        {
+          out[RED]   = layer[RED];
+          out[GREEN] = layer[GREEN];
+          out[BLUE]  = layer[BLUE];
+        }
+      out[ALPHA] = new_alpha;
+      in    += 4;
+      out   += 4;
+      layer += 4;
+ 
+      if (mask)
+        mask++;
+    }
+}
+
+static inline void
+gimp_composite_blend (gfloat                *in,
+                      gfloat                *layer,
+                      gfloat                *mask,
+                      gfloat                *out,
+                      gfloat                 opacity,
+                      glong                  samples,
+                      GimpLayerBlendTRC      blend_trc,
+                      GimpLayerBlendTRC      composite_trc,
+                      GimpLayerCompositeMode composite_mode,
+                      void (*blendfun) (const float *dst,
+                                        const float *src,
+                                              float *out,
+                                              int samples))
+{
+  gfloat *blend_in    = in;
+  gfloat *blend_layer = layer;
+  gfloat *blend_out   = out;
+
+  const Babl *fish_to_blend       = NULL;
+  const Babl *fish_to_composite   = NULL;
+  const Babl *fish_from_composite = NULL;
+ 
+  switch (blend_trc)
+  {
+    default:
+    case GIMP_LAYER_BLEND_RGB_LINEAR:
+      fish_to_blend   =  NULL;
+      switch (composite_trc)
+      {
+        case GIMP_LAYER_BLEND_LAB:
+          fish_to_composite   = _gimp_fish_rgba_to_laba;
+          fish_from_composite = _gimp_fish_laba_to_rgba;
+        default:
+        case GIMP_LAYER_BLEND_RGB_LINEAR:
+          fish_to_composite   = NULL;
+          fish_from_composite = NULL;
+          break;
+        case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+          fish_to_composite   = _gimp_fish_rgba_to_perceptual;
+          fish_from_composite = _gimp_fish_perceptual_to_rgba;
+          break;
+      }
+      break;
+    case GIMP_LAYER_BLEND_LAB:
+      fish_to_blend   = _gimp_fish_rgba_to_laba;
+      switch (composite_trc)
+      {
+        case GIMP_LAYER_BLEND_LAB:
+        default:
+          fish_to_composite = NULL;
+          fish_from_composite = _gimp_fish_laba_to_rgba;
+        case GIMP_LAYER_BLEND_RGB_LINEAR:
+          fish_to_composite = _gimp_fish_laba_to_rgba;
+          fish_from_composite = NULL;
+          break;
+        case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+          fish_to_composite = _gimp_fish_laba_to_perceptual;
+          fish_from_composite = _gimp_fish_perceptual_to_rgba;
+          break;
+      }
+      break;
+    case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+      fish_to_blend = _gimp_fish_rgba_to_perceptual;
+      switch (composite_trc)
+      {
+        case GIMP_LAYER_BLEND_LAB:
+        default:
+          fish_to_composite = _gimp_fish_perceptual_to_laba;
+          fish_from_composite = NULL;
+        case GIMP_LAYER_BLEND_RGB_LINEAR:
+          fish_to_composite = _gimp_fish_perceptual_to_rgba;
+          fish_from_composite = NULL;
+          break;
+        case GIMP_LAYER_BLEND_RGB_PERCEPTUAL:
+          fish_to_composite = NULL;
+          fish_from_composite = _gimp_fish_perceptual_to_rgba;
+          break;
+      }
+      break;
+  }
+
+  if (in == out) /* in-place detected, avoid clobbering since we need to
+                    read it for the compositing stage  */
+    blend_out = alloca (sizeof (gfloat) * 4 * samples);
+
+  if (fish_to_blend)
+  {
+    blend_in    = alloca (sizeof (gfloat) * 4 * samples);
+    blend_layer = alloca (sizeof (gfloat) * 4 * samples);
+    babl_process (fish_to_blend, in,    blend_in,  samples);
+    babl_process (fish_to_blend, layer, blend_layer,  samples);
+  }
+
+  blendfun (blend_in, blend_layer, blend_out, samples);
+
+  if (fish_to_composite)
+    {
+      babl_process (fish_to_composite, blend_in, blend_in,   samples);
+      babl_process (fish_to_composite, blend_out, blend_out, samples);
+    }
+ 
+  switch (composite_mode)
+  {
+    case GIMP_LAYER_COMPOSITE_SRC_ATOP:
+    default:
+      compfun_src_atop (blend_in, blend_out, mask, opacity, out, samples);
+      break;
+    case GIMP_LAYER_COMPOSITE_SRC_OVER:
+      //compfun_src_over (blend_in, blend_out, mask, opacity, out, samples);
+      gimp_operation_normal_process_pixels (blend_in, blend_out, mask, out, opacity, samples, NULL, 0, 0, 0, 
0);
+      break;
+    case GIMP_LAYER_COMPOSITE_DST_ATOP:
+      if (fish_to_composite)
+        babl_process (fish_to_composite, blend_layer, blend_layer,  samples);
+
+      compfun_src_atop (blend_out, blend_in, mask, opacity, out, samples); /* swapped arguments */
+      break;
+    case GIMP_LAYER_COMPOSITE_SRC_IN:
+      compfun_src_in (blend_in, blend_out, mask, opacity, out, samples);
+      break;
+  }
+
+  if (fish_from_composite)
+  {
+    babl_process (fish_from_composite, out, out, samples);
+  }
+}
+ 
+static inline void
+blendfun_screen (const float *dest,
+                 const float *src,
+                 float       *out,
+                 int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+        out[c] = 1.0f - (1.0f - dest[c])   * (1.0f - src[c]);
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_addition (const float *dest,
+                   const float *src,
+                   float       *out,
+                   int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+        out[c] = dest[c] + src[c];
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_subtract (const float *dest,
+                   const float *src,
+                   float       *out,
+                   int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+        out[c] = dest[c] - src[c];
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_multiply (const float *dest,
+                   const float *src,
+                   float       *out,
+                   int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+        out[c] = dest[c] * src[c];
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_normal (const float *dest,
+                 const float *src,
+                 float       *out,
+                 int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+        out[c] = src[c];
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_burn (const float *dest,
+               const float *src,
+               float       *out,
+               int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        gfloat comp = 1.0f - (1.0f - dest[c]) / src[c];
+        /* The CLAMP macro is deliberately inlined and written to map comp ==
+         * NAN (0 / 0) -> 1 */
+        out[c] = comp < 0 ? 0.0f : comp < 1.0f ? comp : 1.0f;
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_darken_only (const float *dest,
+                      const float *src,
+                      float       *out,
+                      int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        out[c] = MIN(dest[c], src[c]);
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_lighten_only (const float *dest,
+                       const float *src,
+                       float       *out,
+                       int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        out[c] = MAX(dest[c], src[c]);
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_difference (const float *dest,
+                     const float *src,
+                     float       *out,
+                     int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        out[c] = dest[c] - src[c];
+        if (out[c] < 0)
+          out[c] = -out[c];
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_divide (const float *dest,
+                 const float *src,
+                 float       *out,
+                 int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        gfloat comp = dest[c] / src[c];
+
+        /* make infinities(or NaN) correspond to a high number, to get more
+         * predictable math, ideally higher than 5.0 but it seems like some
+         * babl conversions might be acting up then
+         */ 
+        if (!(comp > -42949672.0f && comp < 5.0f)) 
+          comp = 5.0f; 
+
+        out[c] = comp;
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_dodge (const float *dest,
+                const float *src,
+                float       *out,
+                int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        gfloat comp = dest[c] / (1.0f - src[c]);
+        comp = MIN (comp, 1.0f);
+
+        out[c] = comp;
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+
+static inline void
+blendfun_grain_extract (const float *dest,
+                        const float *src,
+                        float       *out,
+                        int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        out[c] = dest[c] - src[c] + 0.5f;
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_grain_merge (const float *dest,
+                      const float *src,
+                      float       *out,
+                      int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        out[c] = dest[c] + src[c] - 0.5f;
+      }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+
+static inline void
+blendfun_hardlight (const float *dest,
+                    const float *src,
+                    float       *out,
+                    int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        gfloat comp;
+        if (src[c] > 0.5f)
+          {
+             comp = (1.0f - dest[c]) * (1.0f - (src[c] - 0.5f) * 2.0f);
+             comp = MIN (1 - comp, 1);
+          }
+        else
+          {
+             comp = dest[c] * (src[c] * 2.0f);
+             comp = MIN (comp, 1.0f);
+          }
+        out[c] = comp;
+      }
+      out[ALPHA] = src[ALPHA];
+    }
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_softlight (const float *dest,
+                    const float *src,
+                    float       *out,
+                    int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        gfloat multiply = dest[c] * src[c];
+        gfloat screen = 1.0f - (1.0f - dest[c]) * (1.0f - src[c]);
+        gfloat comp = (1.0f - src[c]) * multiply + dest[c] * screen;
+        out[c] = comp;
+      }
+      out[ALPHA] = src[ALPHA];
+    }
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+
+static inline void
+blendfun_overlay (const float *dest,
+                  const float *src,
+                  float       *out,
+                  int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      int c;
+      for (c = 0; c < 3; c++)
+      {
+        gfloat comp;
+        if (src[c] < 0.5f)
+          {
+             comp = 2.0f * dest[c] * src[c];
+          }
+        else
+          {
+             comp = 1.0f - 2.0f * (1.0f - src[c]) * (1.0f - dest[c]);
+          }
+        out[c] = comp;
+      }
+      out[ALPHA] = src[ALPHA];
+    }
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_hsv_color (const float *dest,
+                    const float *src,
+                    float       *out,
+                    int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+      GimpRGB src_rgb  = {src[0], src[1], src[2]};
+      GimpHSL src_hsl, dest_hsl;
+      gimp_rgb_to_hsl (&dest_rgb, &dest_hsl);
+      gimp_rgb_to_hsl (&src_rgb, &src_hsl);
+      dest_hsl.h = src_hsl.h;
+      dest_hsl.s = src_hsl.s;
+      gimp_hsl_to_rgb (&dest_hsl, &dest_rgb);
+      out[RED]   = dest_rgb.r;
+      out[GREEN] = dest_rgb.g;
+      out[BLUE]  = dest_rgb.b;
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_hsv_hue (const float *dest,
+                  const float *src,
+                  float       *out,
+                  int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+      GimpRGB src_rgb  = {src[0], src[1], src[2]};
+      GimpHSV src_hsv, dest_hsv;
+      gimp_rgb_to_hsv (&dest_rgb, &dest_hsv);
+      gimp_rgb_to_hsv (&src_rgb, &src_hsv);
+      dest_hsv.h = src_hsv.h;
+      gimp_hsv_to_rgb (&dest_hsv, &dest_rgb);
+      out[RED]   = dest_rgb.r;
+      out[GREEN] = dest_rgb.g;
+      out[BLUE]  = dest_rgb.b;
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_hsv_saturation (const float *dest,
+                         const float *src,
+                         float       *out,
+                         int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+      GimpRGB src_rgb  = {src[0], src[1], src[2]};
+      GimpHSV src_hsv, dest_hsv;
+      gimp_rgb_to_hsv (&dest_rgb, &dest_hsv);
+      gimp_rgb_to_hsv (&src_rgb, &src_hsv);
+      dest_hsv.s = src_hsv.s;
+      gimp_hsv_to_rgb (&dest_hsv, &dest_rgb);
+      out[RED]   = dest_rgb.r;
+      out[GREEN] = dest_rgb.g;
+      out[BLUE]  = dest_rgb.b;
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_hsv_value (const float *dest,
+                    const float *src,
+                    float       *out,
+                    int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      GimpRGB dest_rgb = {dest[0], dest[1], dest[2]};
+      GimpRGB src_rgb  = {src[0], src[1], src[2]};
+      GimpHSV src_hsv, dest_hsv;
+      gimp_rgb_to_hsv (&dest_rgb, &dest_hsv);
+      gimp_rgb_to_hsv (&src_rgb, &src_hsv);
+      dest_hsv.v = src_hsv.v;
+      gimp_hsv_to_rgb (&dest_hsv, &dest_rgb);
+      out[RED]   = dest_rgb.r;
+      out[GREEN] = dest_rgb.g;
+      out[BLUE]  = dest_rgb.b;
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_lch_chroma (const float *dest,
+                     const float *src,
+                     float       *out,
+                     int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      gfloat A1 = dest[1];
+      gfloat B1 = dest[2];
+      gfloat c1 = hypotf (A1, B1);
+
+      if (c1 != 0.0f)
+        {
+          gfloat A2 = src[1];
+          gfloat B2 = src[2];
+          gfloat c2 = hypotf (A2, B2);
+          gfloat A  = c2 * A1 / c1;
+          gfloat B  = c2 * B1 / c1;
+          out[0] = dest[0];
+          out[1] = A;
+          out[2] = B;
+        }
+    }
+    out[ALPHA] = src[ALPHA];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_lch_color (const float *dest,
+                    const float *src,
+                    float       *out,
+                    int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      out[0] = dest[0];
+      out[1] = src[1];
+      out[2] = src[2];
+    }
+    out[3] = src[3];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_lch_hue (const float *dest,
+                  const float *src,
+                  float       *out,
+                  int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      gfloat A2 = src[1];
+      gfloat B2 = src[2];
+      gfloat c2 = hypotf (A2, B2);
+
+      if (c2 > 0.1f)
+        {
+          gfloat A1 = dest[1];
+          gfloat B1 = dest[2];
+          gfloat c1 = hypotf (A1, B1);
+          gfloat A = c1 * A2 / c2;
+          gfloat B = c1 * B2 / c2;
+
+          out[0] = dest[0];
+          out[1] = A;
+          out[2] = B;
+        }
+      else
+        {
+          out[0] = dest[0];
+          out[1] = dest[1];
+          out[2] = dest[2];
+        }
+    }
+    out[3] = src[3];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+static inline void
+blendfun_lch_lightness (const float *dest,
+                        const float *src,
+                        float       *out,
+                        int          samples)
+{
+  while (samples--)
+  {
+    if (src[ALPHA] != 0.0f)
+    {
+      out[0] = src[0];
+      out[1] = dest[1];
+      out[2] = dest[2];
+    }
+    out[3] = src[3];
+    out  += 4;
+    src  += 4;
+    dest += 4;
+  }
+}
+
+#endif
diff --git a/app/operations/layer-modes/gimpoperationaddition.c 
b/app/operations/layer-modes/gimpoperationaddition.c
index df412f9..bd0bf7c 100644
--- a/app/operations/layer-modes/gimpoperationaddition.c
+++ b/app/operations/layer-modes/gimpoperationaddition.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationaddition.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_addition_process (GeglOperation       *operation,
@@ -75,61 +76,29 @@ gimp_operation_addition_process (GeglOperation       *operation,
                                  const GeglRectangle *roi,
                                  gint                 level)
 {
-  gfloat opacity  = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_addition_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_addition_process_pixels (in_buf, aux_buf, aux2_buf,
+                          out_buf, layer_mode->opacity, samples, roi, level,
+                          layer_mode->blend_trc, layer_mode->composite_trc,
+                          layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_addition_process_pixels (gfloat              *in,
-                                        gfloat              *layer,
-                                        gfloat              *mask,
-                                        gfloat              *out,
-                                        gfloat               opacity,
-                                        glong                samples,
-                                        const GeglRectangle *roi,
-                                        gint                 level)
+gimp_operation_addition_process_pixels (gfloat                *in,
+                                        gfloat                *layer,
+                                        gfloat                *mask,
+                                        gfloat                *out,
+                                        gfloat                 opacity,
+                                        glong                  samples,
+                                        const GeglRectangle   *roi,
+                                        gint                   level,
+                                        GimpLayerBlendTRC      blend_trc,
+                                        GimpLayerBlendTRC      composite_trc,
+                                        GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] + layer[b];
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+                        blend_trc, composite_trc, composite_mode,
+                        blendfun_addition);
   return TRUE;
 }
+
diff --git a/app/operations/layer-modes/gimpoperationaddition.h 
b/app/operations/layer-modes/gimpoperationaddition.h
index f467b94..01f24bd 100644
--- a/app/operations/layer-modes/gimpoperationaddition.h
+++ b/app/operations/layer-modes/gimpoperationaddition.h
@@ -50,14 +50,17 @@ struct _GimpOperationAdditionClass
 
 GType    gimp_operation_addition_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_addition_process_pixels (gfloat              *in,
-                                                 gfloat              *layer,
-                                                 gfloat              *mask,
-                                                 gfloat              *out,
-                                                 gfloat               opacity,
-                                                 glong                samples,
-                                                 const GeglRectangle *roi,
-                                                 gint                 level);
+gboolean gimp_operation_addition_process_pixels (gfloat                *in,
+                                                 gfloat                *layer,
+                                                 gfloat                *mask,
+                                                 gfloat                *out,
+                                                 gfloat                 opacity,
+                                                 glong                  samples,
+                                                 const GeglRectangle   *roi,
+                                                 gint                   level,
+                                                 GimpLayerBlendTRC      blend_trc, 
+                                                 GimpLayerBlendTRC      composite_trc,
+                                                 GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_ADDITION_H__ */
diff --git a/app/operations/layer-modes/gimpoperationantierase.c 
b/app/operations/layer-modes/gimpoperationantierase.c
index fff71b1..40c1585 100644
--- a/app/operations/layer-modes/gimpoperationantierase.c
+++ b/app/operations/layer-modes/gimpoperationantierase.c
@@ -87,20 +87,23 @@ gimp_operation_anti_erase_process (GeglOperation       *operation,
                                    const GeglRectangle *roi,
                                    gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_anti_erase_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_anti_erase_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_anti_erase_process_pixels (gfloat              *in,
-                                          gfloat              *layer,
-                                          gfloat              *mask,
-                                          gfloat              *out,
-                                          gfloat               opacity,
-                                          glong                samples,
-                                          const GeglRectangle *roi,
-                                          gint                 level)
+gimp_operation_anti_erase_process_pixels (gfloat                *in,
+                                          gfloat                *layer,
+                                          gfloat                *mask,
+                                          gfloat                *out,
+                                          gfloat                 opacity,
+                                          glong                  samples,
+                                          const GeglRectangle   *roi,
+                                          gint                   level,
+                                          GimpLayerBlendTRC      blend_trc,
+                                          GimpLayerBlendTRC      composite_trc,
+                                          GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes/gimpoperationantierase.h 
b/app/operations/layer-modes/gimpoperationantierase.h
index d582792..58e2d41 100644
--- a/app/operations/layer-modes/gimpoperationantierase.h
+++ b/app/operations/layer-modes/gimpoperationantierase.h
@@ -49,14 +49,17 @@ struct _GimpOperationAntiEraseClass
 
 GType    gimp_operation_anti_erase_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_anti_erase_process_pixels (gfloat              *in,
-                                                   gfloat              *layer,
-                                                   gfloat              *mask,
-                                                   gfloat              *out,
-                                                   gfloat               opacity,
-                                                   glong                samples,
-                                                   const GeglRectangle *roi,
-                                                   gint                 level);
+gboolean gimp_operation_anti_erase_process_pixels (gfloat                *in,
+                                                   gfloat                *layer,
+                                                   gfloat                *mask,
+                                                   gfloat                *out,
+                                                   gfloat                 opacity,
+                                                   glong                  samples,
+                                                   const GeglRectangle   *roi,
+                                                   gint                   level,
+                                                   GimpLayerBlendTRC      blend_trc, 
+                                                   GimpLayerBlendTRC      composite_trc,
+                                                   GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_ANTI_ERASE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationbehind.c 
b/app/operations/layer-modes/gimpoperationbehind.c
index 332c73a..cdd58c3 100644
--- a/app/operations/layer-modes/gimpoperationbehind.c
+++ b/app/operations/layer-modes/gimpoperationbehind.c
@@ -74,20 +74,26 @@ gimp_operation_behind_process (GeglOperation       *operation,
                                const GeglRectangle *roi,
                                gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_behind_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_behind_process_pixels (in_buf, aux_buf, aux2_buf, 
+                       out_buf, layer_mode->opacity, samples, roi, level,
+                       layer_mode->blend_trc, layer_mode->composite_trc,
+                       layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_behind_process_pixels (gfloat              *in,
-                                      gfloat              *layer,
-                                      gfloat              *mask,
-                                      gfloat              *out,
-                                      gfloat               opacity,
-                                      glong                samples,
-                                      const GeglRectangle *roi,
-                                      gint                 level)
+gimp_operation_behind_process_pixels (gfloat                *in,
+                                      gfloat                *layer,
+                                      gfloat                *mask,
+                                      gfloat                *out,
+                                      gfloat                 opacity,
+                                      glong                  samples,
+                                      const GeglRectangle   *roi,
+                                      gint                   level,
+                                      GimpLayerBlendTRC      blend_trc,
+                                      GimpLayerBlendTRC      composite_trc,
+                                      GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes/gimpoperationbehind.h 
b/app/operations/layer-modes/gimpoperationbehind.h
index 41c95b2..764f7f6 100644
--- a/app/operations/layer-modes/gimpoperationbehind.h
+++ b/app/operations/layer-modes/gimpoperationbehind.h
@@ -49,14 +49,17 @@ struct _GimpOperationBehindClass
 
 GType    gimp_operation_behind_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_behind_process_pixels (gfloat              *in,
-                                               gfloat              *layer,
-                                               gfloat              *mask,
-                                               gfloat              *out,
-                                               gfloat               opacity,
-                                               glong                samples,
-                                               const GeglRectangle *roi,
-                                               gint                 level);
+gboolean gimp_operation_behind_process_pixels (gfloat                *in,
+                                               gfloat                *layer,
+                                               gfloat                *mask,
+                                               gfloat                *out,
+                                               gfloat                 opacity,
+                                               glong                  samples,
+                                               const GeglRectangle   *roi,
+                                               gint                   level,
+                                               GimpLayerBlendTRC      blend_trc, 
+                                               GimpLayerBlendTRC      composite_trc,
+                                               GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_BEHIND_H__ */
diff --git a/app/operations/layer-modes/gimpoperationburn.c b/app/operations/layer-modes/gimpoperationburn.c
index d35737e..b73df72 100644
--- a/app/operations/layer-modes/gimpoperationburn.c
+++ b/app/operations/layer-modes/gimpoperationburn.c
@@ -27,7 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationburn.h"
-
+#include "gimpblendcomposite.h"
 
 static gboolean gimp_operation_burn_process (GeglOperation       *operation,
                                              void                *in_buf,
@@ -75,65 +75,30 @@ gimp_operation_burn_process (GeglOperation       *operation,
                              const GeglRectangle *roi,
                              gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
+
+  return gimp_operation_burn_process_pixels (in_buf, aux_buf, aux2_buf,
+                  out_buf, layer_mode->opacity, samples, roi, level,
+                  layer_mode->blend_trc, layer_mode->composite_mode,
+                  layer_mode->composite_mode);
+} 
 
-  return gimp_operation_burn_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
-}
 
 gboolean
-gimp_operation_burn_process_pixels (gfloat              *in,
-                                    gfloat              *layer,
-                                    gfloat              *mask,
-                                    gfloat              *out,
-                                    gfloat               opacity,
-                                    glong                samples,
-                                    const GeglRectangle *roi,
-                                    gint                 level)
+gimp_operation_burn_process_pixels (gfloat                *in,
+                                    gfloat                *layer,
+                                    gfloat                *mask,
+                                    gfloat                *out,
+                                    gfloat                 opacity,
+                                    glong                  samples,
+                                    const GeglRectangle   *roi,
+                                    gint                   level,
+                                    GimpLayerBlendTRC      blend_trc,
+                                    GimpLayerBlendTRC      composite_trc,
+                                    GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = 1.0 - (1.0 - in[b]) / layer[b];
-              /* The CLAMP macro is deliberately inlined and
-               * written to map comp == NAN (0 / 0) -> 1
-               */
-              comp = comp < 0 ? 0.0 : comp < 1.0 ? comp : 1.0;
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_burn);
   return TRUE;
 }
+
diff --git a/app/operations/layer-modes/gimpoperationburn.h b/app/operations/layer-modes/gimpoperationburn.h
index 8a1d605..3804e22 100644
--- a/app/operations/layer-modes/gimpoperationburn.h
+++ b/app/operations/layer-modes/gimpoperationburn.h
@@ -50,14 +50,17 @@ struct _GimpOperationBurnClass
 
 GType    gimp_operation_burn_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_burn_process_pixels (gfloat              *in,
-                                             gfloat              *layer,
-                                             gfloat              *mask,
-                                             gfloat              *out,
-                                             gfloat               opacity,
-                                             glong                samples,
-                                             const GeglRectangle *roi,
-                                             gint                 level);
+gboolean gimp_operation_burn_process_pixels (gfloat                *in,
+                                             gfloat                *layer,
+                                             gfloat                *mask,
+                                             gfloat                *out,
+                                             gfloat                 opacity,
+                                             glong                  samples,
+                                             const GeglRectangle   *roi,
+                                             gint                   level,
+                                             GimpLayerBlendTRC      blend_trc, 
+                                             GimpLayerBlendTRC      composite_trc,
+                                             GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_BURN_H__ */
diff --git a/app/operations/layer-modes/gimpoperationcolorerase.c 
b/app/operations/layer-modes/gimpoperationcolorerase.c
index 04e7533..06b8fec 100644
--- a/app/operations/layer-modes/gimpoperationcolorerase.c
+++ b/app/operations/layer-modes/gimpoperationcolorerase.c
@@ -78,20 +78,23 @@ gimp_operation_color_erase_process (GeglOperation       *operation,
                                     const GeglRectangle *roi,
                                     gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_color_erase_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_color_erase_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_color_erase_process_pixels (gfloat              *in,
-                                           gfloat              *layer,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_color_erase_process_pixels (gfloat                *in,
+                                           gfloat                *layer,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes/gimpoperationcolorerase.h 
b/app/operations/layer-modes/gimpoperationcolorerase.h
index 8f3a8f4..b4208b0 100644
--- a/app/operations/layer-modes/gimpoperationcolorerase.h
+++ b/app/operations/layer-modes/gimpoperationcolorerase.h
@@ -49,14 +49,17 @@ struct _GimpOperationColorEraseClass
 
 GType    gimp_operation_color_erase_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_color_erase_process_pixels (gfloat              *in,
-                                                    gfloat              *layer,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
+gboolean gimp_operation_color_erase_process_pixels (gfloat                *in,
+                                                    gfloat                *layer,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_COLOR_ERASE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationdarkenonly.c 
b/app/operations/layer-modes/gimpoperationdarkenonly.c
index 5ce6dca..ff61d54 100644
--- a/app/operations/layer-modes/gimpoperationdarkenonly.c
+++ b/app/operations/layer-modes/gimpoperationdarkenonly.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationdarkenonly.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_darken_only_process (GeglOperation       *operation,
@@ -75,61 +76,25 @@ gimp_operation_darken_only_process (GeglOperation       *operation,
                                     const GeglRectangle *roi,
                                     gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_darken_only_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_darken_only_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_darken_only_process_pixels (gfloat              *in,
-                                           gfloat              *layer,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_darken_only_process_pixels (gfloat                *in,
+                                           gfloat                *layer,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = MIN (in[b], layer[b]);
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_darken_only);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationdarkenonly.h 
b/app/operations/layer-modes/gimpoperationdarkenonly.h
index 578a0f2..8ece2ec 100644
--- a/app/operations/layer-modes/gimpoperationdarkenonly.h
+++ b/app/operations/layer-modes/gimpoperationdarkenonly.h
@@ -50,14 +50,17 @@ struct _GimpOperationDarkenOnlyClass
 
 GType    gimp_operation_darken_only_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_darken_only_process_pixels (gfloat              *in,
-                                                    gfloat              *layer,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
+gboolean gimp_operation_darken_only_process_pixels (gfloat                *in,
+                                                    gfloat                *layer,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DARKEN_ONLY_H__ */
diff --git a/app/operations/layer-modes/gimpoperationdifference.c 
b/app/operations/layer-modes/gimpoperationdifference.c
index fc52ca9..58646fb 100644
--- a/app/operations/layer-modes/gimpoperationdifference.c
+++ b/app/operations/layer-modes/gimpoperationdifference.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationdifference.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_difference_process (GeglOperation       *operation,
@@ -75,62 +76,25 @@ gimp_operation_difference_process (GeglOperation       *operation,
                                    const GeglRectangle *roi,
                                    gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_difference_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_difference_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_difference_process_pixels (gfloat              *in,
-                                          gfloat              *layer,
-                                          gfloat              *mask,
-                                          gfloat              *out,
-                                          gfloat               opacity,
-                                          glong                samples,
-                                          const GeglRectangle *roi,
-                                          gint                 level)
+gimp_operation_difference_process_pixels (gfloat                *in,
+                                          gfloat                *layer,
+                                          gfloat                *mask,
+                                          gfloat                *out,
+                                          gfloat                 opacity,
+                                          glong                  samples,
+                                          const GeglRectangle   *roi,
+                                          gint                   level,
+                                          GimpLayerBlendTRC      blend_trc,
+                                          GimpLayerBlendTRC      composite_trc,
+                                          GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] - layer[b];
-              comp = (comp < 0) ? -comp : comp;
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+     composite_trc, composite_mode, blendfun_difference);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationdifference.h 
b/app/operations/layer-modes/gimpoperationdifference.h
index 72ed1e8..dfe1aa5 100644
--- a/app/operations/layer-modes/gimpoperationdifference.h
+++ b/app/operations/layer-modes/gimpoperationdifference.h
@@ -58,7 +58,10 @@ gboolean gimp_operation_difference_process_pixels (gfloat              *in,
                                                    gfloat               opacity,
                                                    glong                samples,
                                                    const GeglRectangle *roi,
-                                                   gint                 level);
+                                                   gint                 level,
+                                                   GimpLayerBlendTRC    blend_trc, 
+                                                   GimpLayerBlendTRC    composite_trc,
+                                                   GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DIFFERENCE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationdissolve.c 
b/app/operations/layer-modes/gimpoperationdissolve.c
index 1476c17..38afe83 100644
--- a/app/operations/layer-modes/gimpoperationdissolve.c
+++ b/app/operations/layer-modes/gimpoperationdissolve.c
@@ -90,20 +90,23 @@ gimp_operation_dissolve_process (GeglOperation       *operation,
                                  const GeglRectangle *result,
                                  gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*) operation;
 
-  return gimp_operation_dissolve_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
result, level);
+  return gimp_operation_dissolve_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, result, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_dissolve_process_pixels (gfloat              *in,
-                                        gfloat              *aux,
-                                        gfloat              *mask,
-                                        gfloat              *out,
-                                        gfloat               opacity,
-                                        glong                samples,
-                                        const GeglRectangle *result,
-                                        gint                 level)
+gimp_operation_dissolve_process_pixels (gfloat                *in,
+                                        gfloat                *aux,
+                                        gfloat                *mask,
+                                        gfloat                *out,
+                                        gfloat                 opacity,
+                                        glong                  samples,
+                                        const GeglRectangle   *result,
+                                        gint                   level,
+                                        GimpLayerBlendTRC      blend_trc,
+                                        GimpLayerBlendTRC      composite_trc,
+                                        GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
   gint           x, y;
diff --git a/app/operations/layer-modes/gimpoperationdissolve.h 
b/app/operations/layer-modes/gimpoperationdissolve.h
index 89795fb..8b5842f 100644
--- a/app/operations/layer-modes/gimpoperationdissolve.h
+++ b/app/operations/layer-modes/gimpoperationdissolve.h
@@ -49,14 +49,17 @@ struct _GimpOperationDissolve
 
 GType    gimp_operation_dissolve_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_dissolve_process_pixels (gfloat              *in,
-                                                 gfloat              *layer,
-                                                 gfloat              *mask,
-                                                 gfloat              *out,
-                                                 gfloat               opacity,
-                                                 glong                samples,
-                                                 const GeglRectangle *result,
-                                                 gint                 level);
+gboolean gimp_operation_dissolve_process_pixels (gfloat                *in,
+                                                 gfloat                *layer,
+                                                 gfloat                *mask,
+                                                 gfloat                *out,
+                                                 gfloat                 opacity,
+                                                 glong                  samples,
+                                                 const GeglRectangle   *result,
+                                                 gint                   level,
+                                                 GimpLayerBlendTRC      blend_trc, 
+                                                 GimpLayerBlendTRC      composite_trc,
+                                                 GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DISSOLVE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationdivide.c 
b/app/operations/layer-modes/gimpoperationdivide.c
index fc8c897..5b3795f 100644
--- a/app/operations/layer-modes/gimpoperationdivide.c
+++ b/app/operations/layer-modes/gimpoperationdivide.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationdivide.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_divide_process (GeglOperation       *operation,
@@ -75,66 +76,25 @@ gimp_operation_divide_process (GeglOperation       *operation,
                                const GeglRectangle *roi,
                                gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_divide_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_divide_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_divide_process_pixels (gfloat              *in,
-                                      gfloat              *layer,
-                                      gfloat              *mask,
-                                      gfloat              *out,
-                                      gfloat               opacity,
-                                      glong                samples,
-                                      const GeglRectangle *roi,
-                                      gint                 level)
+gimp_operation_divide_process_pixels (gfloat                *in,
+                                      gfloat                *layer,
+                                      gfloat                *mask,
+                                      gfloat                *out,
+                                      gfloat                 opacity,
+                                      glong                  samples,
+                                      const GeglRectangle   *roi,
+                                      gint                   level,
+                                      GimpLayerBlendTRC      blend_trc,
+                                      GimpLayerBlendTRC      composite_trc,
+                                      GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] / layer[b];
-
-              /* make infitinities(or NaN) correspond to a really high number,
-               * to get more predictable math */
-              if (!(comp > -4294967296.0f && comp < 5.0f))
-                comp = 5.0f;
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+   gimp_composite_blend (in, layer, mask, out, opacity, samples,
+                    blend_trc, composite_trc, composite_mode, blendfun_divide);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationdivide.h 
b/app/operations/layer-modes/gimpoperationdivide.h
index 39ead05..2094f09 100644
--- a/app/operations/layer-modes/gimpoperationdivide.h
+++ b/app/operations/layer-modes/gimpoperationdivide.h
@@ -50,14 +50,17 @@ struct _GimpOperationDivideClass
 
 GType    gimp_operation_divide_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_divide_process_pixels (gfloat              *in,
-                                               gfloat              *layer,
-                                               gfloat              *mask,
-                                               gfloat              *out,
-                                               gfloat               opacity,
-                                               glong                samples,
-                                               const GeglRectangle *roi,
-                                               gint                 level);
+gboolean gimp_operation_divide_process_pixels (gfloat                *in,
+                                               gfloat                *layer,
+                                               gfloat                *mask,
+                                               gfloat                *out,
+                                               gfloat                 opacity,
+                                               glong                  samples,
+                                               const GeglRectangle   *roi,
+                                               gint                   level,
+                                               GimpLayerBlendTRC      blend_trc, 
+                                               GimpLayerBlendTRC      composite_trc,
+                                               GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DIVIDE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationdodge.c b/app/operations/layer-modes/gimpoperationdodge.c
index 57488ff..fb29698 100644
--- a/app/operations/layer-modes/gimpoperationdodge.c
+++ b/app/operations/layer-modes/gimpoperationdodge.c
@@ -27,6 +27,7 @@
 #include "operations/operations-types.h"
 
 #include "gimpoperationdodge.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_dodge_process (GeglOperation       *operation,
@@ -75,63 +76,25 @@ gimp_operation_dodge_process (GeglOperation       *operation,
                               const GeglRectangle *roi,
                               gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (void*)operation;
 
-  return gimp_operation_dodge_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_dodge_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_dodge_process_pixels (gfloat              *in,
-                                     gfloat              *layer,
-                                     gfloat              *mask,
-                                     gfloat              *out,
-                                     gfloat               opacity,
-                                     glong                samples,
-                                     const GeglRectangle *roi,
-                                     gint                 level)
+gimp_operation_dodge_process_pixels (gfloat                *in,
+                                     gfloat                *layer,
+                                     gfloat                *mask,
+                                     gfloat                *out,
+                                     gfloat                 opacity,
+                                     glong                  samples,
+                                     const GeglRectangle   *roi,
+                                     gint                   level,
+                                     GimpLayerBlendTRC      blend_trc,
+                                     GimpLayerBlendTRC      composite_trc,
+                                     GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] / (1.0 - layer[b]);
-              comp = MIN (comp, 1.0);
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_dodge);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationdodge.h b/app/operations/layer-modes/gimpoperationdodge.h
index f6e98f4..fe2e179 100644
--- a/app/operations/layer-modes/gimpoperationdodge.h
+++ b/app/operations/layer-modes/gimpoperationdodge.h
@@ -50,14 +50,17 @@ struct _GimpOperationDodgeClass
 
 GType    gimp_operation_dodge_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_dodge_process_pixels (gfloat              *in,
-                                              gfloat              *layer,
-                                              gfloat              *mask,
-                                              gfloat              *out,
-                                              gfloat               opacity,
-                                              glong                samples,
-                                              const GeglRectangle *roi,
-                                              gint                 level);
+gboolean gimp_operation_dodge_process_pixels (gfloat                *in,
+                                              gfloat                *layer,
+                                              gfloat                *mask,
+                                              gfloat                *out,
+                                              gfloat                 opacity,
+                                              glong                  samples,
+                                              const GeglRectangle   *roi,
+                                              gint                   level,
+                                              GimpLayerBlendTRC      blend_trc, 
+                                              GimpLayerBlendTRC      composite_trc,
+                                              GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_DODGE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationerase.c b/app/operations/layer-modes/gimpoperationerase.c
index 138c2df..922df8f 100644
--- a/app/operations/layer-modes/gimpoperationerase.c
+++ b/app/operations/layer-modes/gimpoperationerase.c
@@ -87,20 +87,23 @@ gimp_operation_erase_process (GeglOperation       *operation,
                               const GeglRectangle *roi,
                               gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_erase_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_erase_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_erase_process_pixels (gfloat              *in,
-                                     gfloat              *layer,
-                                     gfloat              *mask,
-                                     gfloat              *out,
-                                     gfloat               opacity,
-                                     glong                samples,
-                                     const GeglRectangle *roi,
-                                     gint                 level)
+gimp_operation_erase_process_pixels (gfloat                *in,
+                                     gfloat                *layer,
+                                     gfloat                *mask,
+                                     gfloat                *out,
+                                     gfloat                 opacity,
+                                     glong                  samples,
+                                     const GeglRectangle   *roi,
+                                     gint                   level,
+                                     GimpLayerBlendTRC      blend_trc,
+                                     GimpLayerBlendTRC      composite_trc,
+                                     GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes/gimpoperationerase.h b/app/operations/layer-modes/gimpoperationerase.h
index ae48749..dcbd93e 100644
--- a/app/operations/layer-modes/gimpoperationerase.h
+++ b/app/operations/layer-modes/gimpoperationerase.h
@@ -49,14 +49,17 @@ struct _GimpOperationEraseClass
 
 GType    gimp_operation_erase_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_erase_process_pixels (gfloat              *in,
-                                              gfloat              *layer,
-                                              gfloat              *mask,
-                                              gfloat              *out,
-                                              gfloat               opacity,
-                                              glong                samples,
-                                              const GeglRectangle *roi,
-                                              gint                 level);
+gboolean gimp_operation_erase_process_pixels (gfloat                *in,
+                                              gfloat                *layer,
+                                              gfloat                *mask,
+                                              gfloat                *out,
+                                              gfloat                 opacity,
+                                              glong                  samples,
+                                              const GeglRectangle   *roi,
+                                              gint                   level,
+                                              GimpLayerBlendTRC      blend_trc, 
+                                              GimpLayerBlendTRC      composite_trc,
+                                              GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_ERASE_MODE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationgrainextract.c 
b/app/operations/layer-modes/gimpoperationgrainextract.c
index a298f99..c23659d 100644
--- a/app/operations/layer-modes/gimpoperationgrainextract.c
+++ b/app/operations/layer-modes/gimpoperationgrainextract.c
@@ -27,16 +27,17 @@
 #include "../operations-types.h"
 
 #include "gimpoperationgrainextract.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_grain_extract_process (GeglOperation       *operation,
-                                                           void                *in_buf,
-                                                           void                *aux_buf,
-                                                           void                *aux2_buf,
-                                                           void                *out_buf,
-                                                           glong                samples,
-                                                           const GeglRectangle *roi,
-                                                           gint                 level);
+                                                      void                *in_buf,
+                                                      void                *aux_buf,
+                                                      void                *aux2_buf,
+                                                      void                *out_buf,
+                                                      glong                samples,
+                                                      const GeglRectangle *roi,
+                                                      gint                 level);
 
 
 G_DEFINE_TYPE (GimpOperationGrainExtract, gimp_operation_grain_extract,
@@ -75,62 +76,24 @@ gimp_operation_grain_extract_process (GeglOperation       *operation,
                                       const GeglRectangle *roi,
                                       gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_grain_extract_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_grain_extract_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_grain_extract_process_pixels (gfloat              *in,
-                                             gfloat              *layer,
-                                             gfloat              *mask,
-                                             gfloat              *out,
-                                             gfloat               opacity,
-                                             glong                samples,
-                                             const GeglRectangle *roi,
-                                             gint                 level)
+gimp_operation_grain_extract_process_pixels (gfloat                *in,
+                                             gfloat                *layer,
+                                             gfloat                *mask,
+                                             gfloat                *out,
+                                             gfloat                 opacity,
+                                             glong                  samples,
+                                             const GeglRectangle   *roi,
+                                             gint                   level,
+                                             GimpLayerBlendTRC      blend_trc,
+                                             GimpLayerBlendTRC      composite_trc,
+                                             GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] - layer[b] + 0.5;
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_grain_extract);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationgrainextract.h 
b/app/operations/layer-modes/gimpoperationgrainextract.h
index 575bc40..3bde1fb 100644
--- a/app/operations/layer-modes/gimpoperationgrainextract.h
+++ b/app/operations/layer-modes/gimpoperationgrainextract.h
@@ -50,14 +50,17 @@ struct _GimpOperationGrainExtractClass
 
 GType    gimp_operation_grain_extract_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_grain_extract_process_pixels (gfloat              *in,
-                                                      gfloat              *layer,
-                                                      gfloat              *mask,
-                                                      gfloat              *out,
-                                                      gfloat               opacity,
-                                                      glong                samples,
-                                                      const GeglRectangle *roi,
-                                                      gint                 level);
+gboolean gimp_operation_grain_extract_process_pixels (gfloat                *in,
+                                                      gfloat                *layer,
+                                                      gfloat                *mask,
+                                                      gfloat                *out,
+                                                      gfloat                 opacity,
+                                                      glong                  samples,
+                                                      const GeglRectangle   *roi,
+                                                      gint                   level,
+                                                      GimpLayerBlendTRC      blend_trc, 
+                                                      GimpLayerBlendTRC      composite_trc,
+                                                      GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_GRAIN_EXTRACT_H__ */
diff --git a/app/operations/layer-modes/gimpoperationgrainmerge.c 
b/app/operations/layer-modes/gimpoperationgrainmerge.c
index f822225..813742f 100644
--- a/app/operations/layer-modes/gimpoperationgrainmerge.c
+++ b/app/operations/layer-modes/gimpoperationgrainmerge.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationgrainmerge.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_grain_merge_process (GeglOperation       *operation,
@@ -75,61 +76,24 @@ gimp_operation_grain_merge_process (GeglOperation       *operation,
                                     const GeglRectangle *roi,
                                     gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_grain_merge_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_grain_merge_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_grain_merge_process_pixels (gfloat              *in,
-                                           gfloat              *layer,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_grain_merge_process_pixels (gfloat                *in,
+                                           gfloat                *layer,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] + layer[b] - 0.5;
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask ++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+     composite_trc, composite_mode, blendfun_grain_merge);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationgrainmerge.h 
b/app/operations/layer-modes/gimpoperationgrainmerge.h
index 47ba029..83fd4d6 100644
--- a/app/operations/layer-modes/gimpoperationgrainmerge.h
+++ b/app/operations/layer-modes/gimpoperationgrainmerge.h
@@ -50,14 +50,17 @@ struct _GimpOperationGrainMergeClass
 
 GType    gimp_operation_grain_merge_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_grain_merge_process_pixels (gfloat              *in,
-                                                    gfloat              *layer,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
+gboolean gimp_operation_grain_merge_process_pixels (gfloat                *in,
+                                                    gfloat                *layer,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_GRAIN_MERGE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationhardlight.c 
b/app/operations/layer-modes/gimpoperationhardlight.c
index 34b8db2..0ada97f 100644
--- a/app/operations/layer-modes/gimpoperationhardlight.c
+++ b/app/operations/layer-modes/gimpoperationhardlight.c
@@ -26,6 +26,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationhardlight.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_hardlight_process (GeglOperation       *operation,
@@ -74,75 +75,25 @@ gimp_operation_hardlight_process (GeglOperation       *operation,
                                   const GeglRectangle *roi,
                                   gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hardlight_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_hardlight_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hardlight_process_pixels (gfloat              *in,
-                                         gfloat              *layer,
-                                         gfloat              *mask,
-                                         gfloat              *out,
-                                         gfloat               opacity,
-                                         glong                samples,
-                                         const GeglRectangle *roi,
-                                         gint                 level)
+gimp_operation_hardlight_process_pixels (gfloat                *in,
+                                         gfloat                *layer,
+                                         gfloat                *mask,
+                                         gfloat                *out,
+                                         gfloat                 opacity,
+                                         glong                  samples,
+                                         const GeglRectangle   *roi,
+                                         gint                   level,
+                                         GimpLayerBlendTRC      blend_trc,
+                                         GimpLayerBlendTRC      composite_trc,
+                                         GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha, new_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
-
-      if (comp_alpha && new_alpha)
-        {
-          gfloat ratio = comp_alpha / new_alpha;
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp;
-
-              if (layer[b] > 0.5)
-                {
-                  comp = (1.0 - in[b]) * (1.0 - (layer[b] - 0.5) * 2.0);
-                  comp = MIN (1 - comp, 1);
-                }
-              else
-                {
-                  comp = in[b] * (layer[b] * 2.0);
-                  comp = MIN (comp, 1.0);
-                }
-
-              out[b] = comp * ratio + in[b] * (1.0 - ratio);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask ++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+             blend_trc, composite_trc, composite_mode, blendfun_hardlight);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationhardlight.h 
b/app/operations/layer-modes/gimpoperationhardlight.h
index 1986600..fe1031e 100644
--- a/app/operations/layer-modes/gimpoperationhardlight.h
+++ b/app/operations/layer-modes/gimpoperationhardlight.h
@@ -49,14 +49,17 @@ struct _GimpOperationHardlightClass
 
 GType    gimp_operation_hardlight_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hardlight_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level);
+gboolean gimp_operation_hardlight_process_pixels (gfloat                *in,
+                                                  gfloat                *layer,
+                                                  gfloat                *mask,
+                                                  gfloat                *out,
+                                                  gfloat                 opacity,
+                                                  glong                  samples,
+                                                  const GeglRectangle   *roi,
+                                                  gint                   level,
+                                                  GimpLayerBlendTRC      blend_trc, 
+                                                  GimpLayerBlendTRC      composite_trc,
+                                                  GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HARDLIGHT_H__ */
diff --git a/app/operations/layer-modes/gimpoperationhsvcolor.c 
b/app/operations/layer-modes/gimpoperationhsvcolor.c
index 756bcb9..401be9b 100644
--- a/app/operations/layer-modes/gimpoperationhsvcolor.c
+++ b/app/operations/layer-modes/gimpoperationhsvcolor.c
@@ -31,6 +31,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationhsvcolor.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_hsv_color_process (GeglOperation       *operation,
@@ -79,74 +80,25 @@ gimp_operation_hsv_color_process (GeglOperation       *operation,
                                   const GeglRectangle *roi,
                                   gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hsv_color_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_hsv_color_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_color_process_pixels (gfloat              *in,
-                                         gfloat              *layer,
-                                         gfloat              *mask,
-                                         gfloat              *out,
-                                         gfloat               opacity,
-                                         glong                samples,
-                                         const GeglRectangle *roi,
-                                         gint                 level)
+gimp_operation_hsv_color_process_pixels (gfloat                *in,
+                                         gfloat                *layer,
+                                         gfloat                *mask,
+                                         gfloat                *out,
+                                         gfloat                 opacity,
+                                         glong                  samples,
+                                         const GeglRectangle   *roi,
+                                         gint                   level,
+                                         GimpLayerBlendTRC      blend_trc,
+                                         GimpLayerBlendTRC      composite_trc,
+                                         GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      GimpHSL layer_hsl, out_hsl;
-      GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
-      GimpRGB out_rgb   = {in[0], in[1], in[2]};
-      gfloat  comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha)
-        {
-          gint   b;
-          gfloat out_tmp[3];
-
-          gimp_rgb_to_hsl (&layer_rgb, &layer_hsl);
-          gimp_rgb_to_hsl (&out_rgb, &out_hsl);
-
-          out_hsl.h = layer_hsl.h;
-          out_hsl.s = layer_hsl.s;
-          gimp_hsl_to_rgb (&out_hsl, &out_rgb);
-
-          out_tmp[0] = out_rgb.r;
-          out_tmp[1] = out_rgb.g;
-          out_tmp[2] = out_rgb.b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = out_tmp[b] * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+                blend_trc, composite_trc, composite_mode, blendfun_hsv_color);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationhsvcolor.h 
b/app/operations/layer-modes/gimpoperationhsvcolor.h
index b7c607e..2b825b4 100644
--- a/app/operations/layer-modes/gimpoperationhsvcolor.h
+++ b/app/operations/layer-modes/gimpoperationhsvcolor.h
@@ -50,14 +50,17 @@ struct _GimpOperationHsvColorClass
 
 GType    gimp_operation_hsv_color_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_color_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level);
+gboolean gimp_operation_hsv_color_process_pixels (gfloat                *in,
+                                                  gfloat                *layer,
+                                                  gfloat                *mask,
+                                                  gfloat                *out,
+                                                  gfloat                 opacity,
+                                                  glong                  samples,
+                                                  const GeglRectangle   *roi,
+                                                  gint                   level,
+                                                  GimpLayerBlendTRC      blend_trc, 
+                                                  GimpLayerBlendTRC      composite_trc,
+                                                  GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_COLOR_H__ */
diff --git a/app/operations/layer-modes/gimpoperationhsvhue.c 
b/app/operations/layer-modes/gimpoperationhsvhue.c
index e5b2595..54865df 100644
--- a/app/operations/layer-modes/gimpoperationhsvhue.c
+++ b/app/operations/layer-modes/gimpoperationhsvhue.c
@@ -31,6 +31,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationhsvhue.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_hsv_hue_process (GeglOperation       *operation,
@@ -79,79 +80,25 @@ gimp_operation_hsv_hue_process (GeglOperation       *operation,
                                 const GeglRectangle *roi,
                                 gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_hsv_hue_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_hsv_hue_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_hue_process_pixels (gfloat              *in,
-                                       gfloat              *layer,
-                                       gfloat              *mask,
-                                       gfloat              *out,
-                                       gfloat               opacity,
-                                       glong                samples,
-                                       const GeglRectangle *roi,
-                                       gint                 level)
+gimp_operation_hsv_hue_process_pixels (gfloat                *in,
+                                       gfloat                *layer,
+                                       gfloat                *mask,
+                                       gfloat                *out,
+                                       gfloat                 opacity,
+                                       glong                  samples,
+                                       const GeglRectangle   *roi,
+                                       gint                   level,
+                                       GimpLayerBlendTRC      blend_trc,
+                                       GimpLayerBlendTRC      composite_trc,
+                                       GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      GimpHSV layer_hsv, out_hsv;
-      GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
-      GimpRGB out_rgb   = {in[0], in[1], in[2]};
-      gfloat  comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-          gfloat out_tmp[3];
-
-          gimp_rgb_to_hsv (&layer_rgb, &layer_hsv);
-          gimp_rgb_to_hsv (&out_rgb, &out_hsv);
-
-          /*  Composition should have no effect if saturation is zero.
-           *  otherwise, black would be painted red (see bug #123296).
-           */
-          if (layer_hsv.s)
-            {
-              out_hsv.h = layer_hsv.h;
-            }
-          gimp_hsv_to_rgb (&out_hsv, &out_rgb);
-
-          out_tmp[0] = out_rgb.r;
-          out_tmp[1] = out_rgb.g;
-          out_tmp[2] = out_rgb.b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = out_tmp[b] * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_hsv_hue);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationhsvhue.h 
b/app/operations/layer-modes/gimpoperationhsvhue.h
index 18ab422..15a37ae 100644
--- a/app/operations/layer-modes/gimpoperationhsvhue.h
+++ b/app/operations/layer-modes/gimpoperationhsvhue.h
@@ -50,14 +50,17 @@ struct _GimpOperationHsvHueClass
 
 GType    gimp_operation_hsv_hue_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_hue_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level);
+gboolean gimp_operation_hsv_hue_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc, 
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_HUE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationhsvsaturation.c 
b/app/operations/layer-modes/gimpoperationhsvsaturation.c
index 88e6ddb..35d7b52 100644
--- a/app/operations/layer-modes/gimpoperationhsvsaturation.c
+++ b/app/operations/layer-modes/gimpoperationhsvsaturation.c
@@ -31,6 +31,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationhsvsaturation.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_hsv_saturation_process (GeglOperation       *operation,
@@ -79,73 +80,24 @@ gimp_operation_hsv_saturation_process (GeglOperation       *operation,
                                        const GeglRectangle *roi,
                                        gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_hsv_saturation_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_hsv_saturation_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_saturation_process_pixels (gfloat              *in,
-                                              gfloat              *layer,
-                                              gfloat              *mask,
-                                              gfloat              *out,
-                                              gfloat               opacity,
-                                              glong                samples,
-                                              const GeglRectangle *roi,
-                                              gint                 level)
+gimp_operation_hsv_saturation_process_pixels (gfloat                *in,
+                                              gfloat                *layer,
+                                              gfloat                *mask,
+                                              gfloat                *out,
+                                              gfloat                 opacity,
+                                              glong                  samples,
+                                              const GeglRectangle   *roi,
+                                              gint                   level,
+                                              GimpLayerBlendTRC      blend_trc,
+                                              GimpLayerBlendTRC      composite_trc,
+                                              GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      GimpHSV layer_hsv, out_hsv;
-      GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
-      GimpRGB out_rgb   = {in[0], in[1], in[2]};
-      gfloat  comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-          gfloat out_tmp[3];
-
-          gimp_rgb_to_hsv (&layer_rgb, &layer_hsv);
-          gimp_rgb_to_hsv (&out_rgb, &out_hsv);
-
-          out_hsv.s = layer_hsv.s;
-          gimp_hsv_to_rgb (&out_hsv, &out_rgb);
-
-          out_tmp[0] = out_rgb.r;
-          out_tmp[1] = out_rgb.g;
-          out_tmp[2] = out_rgb.b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = out_tmp[b] * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_hsv_saturation);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationhsvsaturation.h 
b/app/operations/layer-modes/gimpoperationhsvsaturation.h
index 5031c80..7777e62 100644
--- a/app/operations/layer-modes/gimpoperationhsvsaturation.h
+++ b/app/operations/layer-modes/gimpoperationhsvsaturation.h
@@ -50,14 +50,17 @@ struct _GimpOperationHsvSaturationClass
 
 GType    gimp_operation_hsv_saturation_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_saturation_process_pixels (gfloat              *in,
-                                                       gfloat              *layer,
-                                                       gfloat              *mask,
-                                                       gfloat              *out,
-                                                       gfloat               opacity,
-                                                       glong                samples,
-                                                       const GeglRectangle *roi,
-                                                       gint                 level);
+gboolean gimp_operation_hsv_saturation_process_pixels (gfloat                *in,
+                                                       gfloat                *layer,
+                                                       gfloat                *mask,
+                                                       gfloat                *out,
+                                                       gfloat                 opacity,
+                                                       glong                  samples,
+                                                       const GeglRectangle   *roi,
+                                                       gint                   level,
+                                                       GimpLayerBlendTRC      blend_trc, 
+                                                       GimpLayerBlendTRC      composite_trc,
+                                                       GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_SATURATION_H__ */
diff --git a/app/operations/layer-modes/gimpoperationhsvvalue.c 
b/app/operations/layer-modes/gimpoperationhsvvalue.c
index 4d1c2c3..d37e75a 100644
--- a/app/operations/layer-modes/gimpoperationhsvvalue.c
+++ b/app/operations/layer-modes/gimpoperationhsvvalue.c
@@ -31,6 +31,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationhsvvalue.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_hsv_value_process (GeglOperation       *operation,
@@ -79,61 +80,24 @@ gimp_operation_hsv_value_process (GeglOperation       *operation,
                                   const GeglRectangle *roi,
                                   gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_hsv_value_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_hsv_value_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_hsv_value_process_pixels (gfloat              *in,
-                                         gfloat              *layer,
-                                         gfloat              *mask,
-                                         gfloat              *out,
-                                         gfloat               opacity,
-                                         glong                samples,
-                                         const GeglRectangle *roi,
-                                         gint                 level)
+gimp_operation_hsv_value_process_pixels (gfloat                *in,
+                                         gfloat                *layer,
+                                         gfloat                *mask,
+                                         gfloat                *out,
+                                         gfloat                 opacity,
+                                         glong                  samples,
+                                         const GeglRectangle   *roi,
+                                         gint                   level,
+                                         GimpLayerBlendTRC      blend_trc,
+                                         GimpLayerBlendTRC      composite_trc,
+                                         GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      GimpHSV layer_hsv, out_hsv;
-      GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
-      GimpRGB out_rgb   = {in[0], in[1], in[2]};
-      gfloat  comp_alpha = layer[ALPHA] * opacity;
-
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gimp_rgb_to_hsv (&layer_rgb, &layer_hsv);
-          gimp_rgb_to_hsv (&out_rgb, &out_hsv);
-
-          out_hsv.v = layer_hsv.v;
-          gimp_hsv_to_rgb (&out_hsv, &out_rgb);
-
-          out[RED]   = out_rgb.r * comp_alpha + in[RED]   * (1.0 - comp_alpha);
-          out[GREEN] = out_rgb.g * comp_alpha + in[GREEN] * (1.0 - comp_alpha);
-          out[BLUE]  = out_rgb.b * comp_alpha + in[BLUE]  * (1.0 - comp_alpha);
-        }
-      else
-        {
-          out[RED]   = in[RED];
-          out[GREEN] = in[GREEN];
-          out[BLUE]  = in[BLUE];
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_hsv_value);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationhsvvalue.h 
b/app/operations/layer-modes/gimpoperationhsvvalue.h
index 081ed31..ab81972 100644
--- a/app/operations/layer-modes/gimpoperationhsvvalue.h
+++ b/app/operations/layer-modes/gimpoperationhsvvalue.h
@@ -50,14 +50,17 @@ struct _GimpOperationHsvValueClass
 
 GType    gimp_operation_hsv_value_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_hsv_value_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level);
+gboolean gimp_operation_hsv_value_process_pixels (gfloat                *in,
+                                                  gfloat                *layer,
+                                                  gfloat                *mask,
+                                                  gfloat                *out,
+                                                  gfloat                 opacity,
+                                                  glong                  samples,
+                                                  const GeglRectangle   *roi,
+                                                  gint                   level,
+                                                  GimpLayerBlendTRC      blend_trc, 
+                                                  GimpLayerBlendTRC      composite_trc,
+                                                  GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_HSV_VALUE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationlchchroma.c 
b/app/operations/layer-modes/gimpoperationlchchroma.c
index 5a08911..35f206f 100644
--- a/app/operations/layer-modes/gimpoperationlchchroma.c
+++ b/app/operations/layer-modes/gimpoperationlchchroma.c
@@ -26,6 +26,7 @@
 #include <math.h>
 #include "../operations-types.h"
 #include "gimpoperationlchchroma.h"
+#include "gimpblendcomposite.h"
 
 static gboolean gimp_operation_lch_chroma_process (GeglOperation       *operation,
                                                    void                *in_buf,
@@ -83,7 +84,7 @@ gimp_operation_lch_chroma_process (GeglOperation       *operation,
 
   return (linear ? gimp_operation_lch_chroma_process_pixels_linear :
                    gimp_operation_lch_chroma_process_pixels)
-    (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level);
+    (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level, gimp_op->blend_trc, 
gimp_op->composite_trc, gimp_op->composite_mode);
 }
 
 static void
@@ -122,39 +123,19 @@ chroma_pre_process (const Babl   *from_fish,
   babl_process (to_fish, out, out, samples);
 }
 
+/* XXX: this and pre_process should be removed */
 gboolean
-gimp_operation_lch_chroma_process_pixels_linear (gfloat              *in,
-                                                 gfloat              *layer,
-                                                 gfloat              *mask,
-                                                 gfloat              *out,
-                                                 gfloat               opacity,
-                                                 glong                samples,
-                                                 const GeglRectangle *roi,
-                                                 gint                 level)
-{
-  static const Babl *from_fish;
-  static const Babl *to_fish;
-  
-  if (!from_fish)
-    from_fish = babl_fish ("RGBA float", "CIE Lab alpha float");
-  if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
-
-  chroma_pre_process (from_fish, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
-  return TRUE;
-}
-
-gboolean
-gimp_operation_lch_chroma_process_pixels (gfloat              *in,
-                                          gfloat              *layer,
-                                          gfloat              *mask,
-                                          gfloat              *out,
-                                          gfloat               opacity,
-                                          glong                samples,
-                                          const GeglRectangle *roi,
-                                          gint                 level)
+gimp_operation_lch_chroma_process_pixels (gfloat                *in,
+                                          gfloat                *layer,
+                                          gfloat                *mask,
+                                          gfloat                *out,
+                                          gfloat                 opacity,
+                                          glong                  samples,
+                                          const GeglRectangle   *roi,
+                                          gint                   level,
+                                          GimpLayerBlendTRC      blend_trc,
+                                          GimpLayerBlendTRC      composite_trc,
+                                          GimpLayerCompositeMode composite_mode)
 {
   static const Babl *from_fish = NULL;
   static const Babl *to_fish = NULL;
@@ -165,8 +146,25 @@ gimp_operation_lch_chroma_process_pixels (gfloat              *in,
      to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
 
   chroma_pre_process (from_fish, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
+  compfun_src_atop (in, layer, mask, opacity, out, samples);
 
   return TRUE;
 }
 
+gboolean
+gimp_operation_lch_chroma_process_pixels_linear (gfloat                *in,
+                                                 gfloat                *layer,
+                                                 gfloat                *mask,
+                                                 gfloat                *out,
+                                                 gfloat                 opacity,
+                                                 glong                  samples,
+                                                 const GeglRectangle   *roi,
+                                                 gint                   level,
+                                                 GimpLayerBlendTRC      blend_trc,
+                                                 GimpLayerBlendTRC      composite_trc,
+                                                 GimpLayerCompositeMode composite_mode)
+{
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_lch_chroma);
+  return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationlchchroma.h 
b/app/operations/layer-modes/gimpoperationlchchroma.h
index 123d59d..f3d8e35 100644
--- a/app/operations/layer-modes/gimpoperationlchchroma.h
+++ b/app/operations/layer-modes/gimpoperationlchchroma.h
@@ -58,16 +58,22 @@ gboolean gimp_operation_lch_chroma_process_pixels_linear (gfloat              *i
                                                           gfloat               opacity,
                                                           glong                samples,
                                                           const GeglRectangle *roi,
-                                                          gint                 level);
+                                                          gint                 level,
+                                                          GimpLayerBlendTRC    blend_trc, 
+                                                          GimpLayerBlendTRC    composite_trc,
+                                                          GimpLayerCompositeMode composite_mode);
 
-gboolean gimp_operation_lch_chroma_process_pixels        (gfloat              *in,
-                                                          gfloat              *layer,
-                                                          gfloat              *mask,
-                                                          gfloat              *out,
-                                                          gfloat               opacity,
-                                                          glong                samples,
-                                                          const GeglRectangle *roi,
-                                                          gint                 level);
+gboolean gimp_operation_lch_chroma_process_pixels        (gfloat                *in,
+                                                          gfloat                *layer,
+                                                          gfloat                *mask,
+                                                          gfloat                *out,
+                                                          gfloat                 opacity,
+                                                          glong                  samples,
+                                                          const GeglRectangle   *roi,
+                                                          gint                   level,
+                                                          GimpLayerBlendTRC      blend_trc, 
+                                                          GimpLayerBlendTRC      composite_trc,
+                                                          GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_LCH_CHROMA_H__ */
diff --git a/app/operations/layer-modes/gimpoperationlchcolor.c 
b/app/operations/layer-modes/gimpoperationlchcolor.c
index 05badeb..4efc26e 100644
--- a/app/operations/layer-modes/gimpoperationlchcolor.c
+++ b/app/operations/layer-modes/gimpoperationlchcolor.c
@@ -25,6 +25,7 @@
 #include <gegl-plugin.h>
 #include "../operations-types.h"
 #include "gimpoperationlchcolor.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_lch_color_process (GeglOperation       *operation,
@@ -78,12 +79,10 @@ gimp_operation_lch_color_process (GeglOperation       *operation,
                                   gint                 level)
 {
   GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation);
-  gfloat                       opacity = gimp_op->opacity;
-  gboolean                     linear  = gimp_op->linear;
 
-  return (linear ? gimp_operation_lch_color_process_pixels_linear :
+  return (gimp_op->linear ? gimp_operation_lch_color_process_pixels_linear :
                    gimp_operation_lch_color_process_pixels)
-    (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level);
+    (in_buf, aux_buf, aux2_buf, out_buf, gimp_op->opacity, samples, roi, level, gimp_op->blend_trc, 
gimp_op->composite_trc, gimp_op->composite_mode);
 }
 
 static void
@@ -112,56 +111,52 @@ color_pre_process (const Babl   *from_fish_la,
   babl_process (to_fish, out, out, samples);
 }
 
+/* XXX: should be removed along with the pre_process fun */
 gboolean
-gimp_operation_lch_color_process_pixels_linear (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level)
+gimp_operation_lch_color_process_pixels (gfloat                *in,
+                                         gfloat                *layer,
+                                         gfloat                *mask,
+                                         gfloat                *out,
+                                         gfloat                 opacity,
+                                         glong                  samples,
+                                         const GeglRectangle   *roi,
+                                         gint                   level,
+                                         GimpLayerBlendTRC      blend_trc,
+                                         GimpLayerBlendTRC      composite_trc,
+                                         GimpLayerCompositeMode composite_mode)
 {
   static const Babl *from_fish_laba = NULL;
   static const Babl *from_fish_la = NULL;
   static const Babl *to_fish = NULL;
   
   if (!from_fish_laba)
-    from_fish_laba  = babl_fish ("RGBA float", "CIE Lab alpha float");
+    from_fish_laba  = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
   if (!from_fish_la)
-    from_fish_la =  babl_fish ("RGBA float", "CIE L alpha float");
+    from_fish_la =  babl_fish ("R'G'B'A float", "CIE L alpha float");
   if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
+     to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
 
   color_pre_process (from_fish_la, from_fish_laba, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
+  compfun_src_atop (in, layer, mask, opacity, out, samples);
 
   return TRUE;
 }
 
+
 gboolean
-gimp_operation_lch_color_process_pixels (gfloat              *in,
-                                         gfloat              *layer,
-                                         gfloat              *mask,
-                                         gfloat              *out,
-                                         gfloat               opacity,
-                                         glong                samples,
-                                         const GeglRectangle *roi,
-                                         gint                 level)
+gimp_operation_lch_color_process_pixels_linear (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc,
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode)
 {
-  static const Babl *from_fish_laba = NULL;
-  static const Babl *from_fish_la = NULL;
-  static const Babl *to_fish = NULL;
-  
-  if (!from_fish_laba)
-    from_fish_laba  = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
-  if (!from_fish_la)
-    from_fish_la =  babl_fish ("R'G'B'A float", "CIE L alpha float");
-  if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
-
-  color_pre_process (from_fish_la, from_fish_laba, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_lch_color);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationlchcolor.h 
b/app/operations/layer-modes/gimpoperationlchcolor.h
index 8f2f10c..c810579 100644
--- a/app/operations/layer-modes/gimpoperationlchcolor.h
+++ b/app/operations/layer-modes/gimpoperationlchcolor.h
@@ -51,23 +51,29 @@ struct _GimpOperationLchColorClass
 
 GType    gimp_operation_lch_color_get_type              (void) G_GNUC_CONST;
 
-gboolean gimp_operation_lch_color_process_pixels_linear (gfloat              *in,
-                                                         gfloat              *layer,
-                                                         gfloat              *mask,
-                                                         gfloat              *out,
-                                                         gfloat               opacity,
-                                                         glong                samples,
-                                                         const GeglRectangle *roi,
-                                                         gint                 level);
+gboolean gimp_operation_lch_color_process_pixels_linear (gfloat                *in,
+                                                         gfloat                *layer,
+                                                         gfloat                *mask,
+                                                         gfloat                *out,
+                                                         gfloat                 opacity,
+                                                         glong                  samples,
+                                                         const GeglRectangle   *roi,
+                                                         gint                   level,
+                                                         GimpLayerBlendTRC      blend_trc, 
+                                                         GimpLayerBlendTRC      composite_trc,
+                                                         GimpLayerCompositeMode composite_mode);
 
-gboolean gimp_operation_lch_color_process_pixels        (gfloat              *in,
-                                                         gfloat              *layer,
-                                                         gfloat              *mask,
-                                                         gfloat              *out,
-                                                         gfloat               opacity,
-                                                         glong                samples,
-                                                         const GeglRectangle *roi,
-                                                         gint                 level);
+gboolean gimp_operation_lch_color_process_pixels        (gfloat                *in,
+                                                         gfloat                *layer,
+                                                         gfloat                *mask,
+                                                         gfloat                *out,
+                                                         gfloat                 opacity,
+                                                         glong                  samples,
+                                                         const GeglRectangle   *roi,
+                                                         gint                   level,
+                                                         GimpLayerBlendTRC      blend_trc, 
+                                                         GimpLayerBlendTRC      composite_trc,
+                                                         GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_LCH_COLOR_H__ */
diff --git a/app/operations/layer-modes/gimpoperationlchhue.c 
b/app/operations/layer-modes/gimpoperationlchhue.c
index 38265f6..0e89002 100644
--- a/app/operations/layer-modes/gimpoperationlchhue.c
+++ b/app/operations/layer-modes/gimpoperationlchhue.c
@@ -26,6 +26,7 @@
 #include <math.h>
 #include "../operations-types.h"
 #include "gimpoperationlchhue.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_lch_hue_process (GeglOperation       *operation,
@@ -78,13 +79,11 @@ gimp_operation_lch_hue_process (GeglOperation       *operation,
                                 const GeglRectangle *roi,
                                 gint                 level)
 {
-  GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation);
-  gfloat                       opacity = gimp_op->opacity;
-  gboolean                     linear  = gimp_op->linear;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return (linear ? gimp_operation_lch_hue_process_pixels_linear :
+  return (layer_mode->linear ? gimp_operation_lch_hue_process_pixels_linear :
                    gimp_operation_lch_hue_process_pixels)
-    (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level);
+    (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, 
layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 static void
@@ -123,50 +122,49 @@ hue_pre_process (const Babl   *from_fish,
   babl_process (to_fish, out, out, samples);
 }
 
+/* XXX: this should be removed along with _pre_process */
 gboolean
-gimp_operation_lch_hue_process_pixels_linear (gfloat              *in,
-                                              gfloat              *layer,
-                                              gfloat              *mask,
-                                              gfloat              *out,
-                                              gfloat               opacity,
-                                              glong                samples,
-                                              const GeglRectangle *roi,
-                                              gint                 level)
+gimp_operation_lch_hue_process_pixels (gfloat                *in,
+                                       gfloat                *layer,
+                                       gfloat                *mask,
+                                       gfloat                *out,
+                                       gfloat                 opacity,
+                                       glong                  samples,
+                                       const GeglRectangle   *roi,
+                                       gint                   level,
+                                       GimpLayerBlendTRC      blend_trc,
+                                       GimpLayerBlendTRC      composite_trc,
+                                       GimpLayerCompositeMode composite_mode)
 {
   static const Babl *from_fish = NULL;
   static const Babl *to_fish = NULL;
   
   if (!from_fish)
-    from_fish = babl_fish ("RGBA float", "CIE Lab alpha float");
+    from_fish = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
   if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
+     to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
 
   hue_pre_process (from_fish, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
+  compfun_src_atop (in, layer, mask, opacity, out, samples);
 
   return TRUE;
 }
 
+
 gboolean
-gimp_operation_lch_hue_process_pixels (gfloat              *in,
-                                       gfloat              *layer,
-                                       gfloat              *mask,
-                                       gfloat              *out,
-                                       gfloat               opacity,
-                                       glong                samples,
-                                       const GeglRectangle *roi,
-                                       gint                 level)
+gimp_operation_lch_hue_process_pixels_linear (gfloat                *in,
+                                              gfloat                *layer,
+                                              gfloat                *mask,
+                                              gfloat                *out,
+                                              gfloat                 opacity,
+                                              glong                  samples,
+                                              const GeglRectangle   *roi,
+                                              gint                   level,
+                                              GimpLayerBlendTRC      blend_trc,
+                                              GimpLayerBlendTRC      composite_trc,
+                                              GimpLayerCompositeMode composite_mode)
 {
-  static const Babl *from_fish = NULL;
-  static const Babl *to_fish = NULL;
-  
-  if (!from_fish)
-    from_fish = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
-  if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
-
-  hue_pre_process (from_fish, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_lch_hue);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationlchhue.h 
b/app/operations/layer-modes/gimpoperationlchhue.h
index 99472b7..19e582c 100644
--- a/app/operations/layer-modes/gimpoperationlchhue.h
+++ b/app/operations/layer-modes/gimpoperationlchhue.h
@@ -51,23 +51,28 @@ struct _GimpOperationLchHueClass
 
 GType    gimp_operation_lch_hue_get_type              (void) G_GNUC_CONST;
 
-gboolean gimp_operation_lch_hue_process_pixels_linear (gfloat              *in,
-                                                       gfloat              *layer,
-                                                       gfloat              *mask,
-                                                       gfloat              *out,
-                                                       gfloat               opacity,
-                                                       glong                samples,
-                                                       const GeglRectangle *roi,
-                                                       gint                 level);
-
-gboolean gimp_operation_lch_hue_process_pixels        (gfloat              *in,
-                                                       gfloat              *layer,
-                                                       gfloat              *mask,
-                                                       gfloat              *out,
-                                                       gfloat               opacity,
-                                                       glong                samples,
-                                                       const GeglRectangle *roi,
-                                                       gint                 level);
+gboolean gimp_operation_lch_hue_process_pixels_linear (gfloat                *in,
+                                                       gfloat                *layer,
+                                                       gfloat                *mask,
+                                                       gfloat                *out,
+                                                       gfloat                 opacity,
+                                                       glong                  samples,
+                                                       const GeglRectangle   *roi,
+                                                       gint                   level,
+                                                       GimpLayerBlendTRC      blend_trc, 
+                                                       GimpLayerBlendTRC      composite_trc,
+                                                       GimpLayerCompositeMode composite_mode);
 
+gboolean gimp_operation_lch_hue_process_pixels        (gfloat                *in,
+                                                       gfloat                *layer,
+                                                       gfloat                *mask,
+                                                       gfloat                *out,
+                                                       gfloat                 opacity,
+                                                       glong                  samples,
+                                                       const GeglRectangle   *roi,
+                                                       gint                   level,
+                                                       GimpLayerBlendTRC      blend_trc, 
+                                                       GimpLayerBlendTRC      composite_trc,
+                                                       GimpLayerCompositeMode composite_mode);
 
 #endif /* __GIMP_OPERATION_LCH_HUE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationlchlightness.c 
b/app/operations/layer-modes/gimpoperationlchlightness.c
index f452352..abcf698 100644
--- a/app/operations/layer-modes/gimpoperationlchlightness.c
+++ b/app/operations/layer-modes/gimpoperationlchlightness.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationlchlightness.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_lch_lightness_process (GeglOperation       *operation,
@@ -78,13 +79,9 @@ gimp_operation_lch_lightness_process (GeglOperation       *operation,
                                       const GeglRectangle *roi,
                                       gint                 level)
 {
-  GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation);
-  gfloat                       opacity = gimp_op->opacity;
-  gboolean                     linear  = gimp_op->linear;
-
-  return (linear ? gimp_operation_lch_lightness_process_pixels_linear :
-                   gimp_operation_lch_lightness_process_pixels)
-    (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return (layer_mode->linear ? gimp_operation_lch_lightness_process_pixels_linear : 
gimp_operation_lch_lightness_process_pixels)
+    (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, 
layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 static void
@@ -108,57 +105,53 @@ lightness_pre_process (const Babl   *from_fish_la,
   babl_process (to_fish, out, out, samples);
 }
 
+/* XXX: this should be remove along with _pre_process */
 gboolean
-gimp_operation_lch_lightness_process_pixels_linear (gfloat              *in,
-                                                    gfloat              *layer,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level)
+gimp_operation_lch_lightness_process_pixels (gfloat                *in,
+                                             gfloat                *layer,
+                                             gfloat                *mask,
+                                             gfloat                *out,
+                                             gfloat                 opacity,
+                                             glong                  samples,
+                                             const GeglRectangle   *roi,
+                                             gint                   level,
+                                             GimpLayerBlendTRC      blend_trc,
+                                             GimpLayerBlendTRC      composite_trc,
+                                             GimpLayerCompositeMode composite_mode)
 {
   static const Babl *from_fish_laba = NULL;
   static const Babl *from_fish_la = NULL;
   static const Babl *to_fish = NULL;
   
   if (!from_fish_laba)
-    from_fish_laba  = babl_fish ("RGBA float", "CIE Lab alpha float");
+    from_fish_laba  = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
   if (!from_fish_la)
-    from_fish_la =  babl_fish ("RGBA float", "CIE L alpha float");
+    from_fish_la =  babl_fish ("R'G'B'A float", "CIE L alpha float");
   if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "RGBA float");
+     to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
+
 
   lightness_pre_process (from_fish_la, from_fish_laba, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
+  compfun_src_atop (in, layer, mask, opacity, out, samples);
 
   return TRUE;
 }
 
+
 gboolean
-gimp_operation_lch_lightness_process_pixels (gfloat              *in,
-                                             gfloat              *layer,
-                                             gfloat              *mask,
-                                             gfloat              *out,
-                                             gfloat               opacity,
-                                             glong                samples,
-                                             const GeglRectangle *roi,
-                                             gint                 level)
+gimp_operation_lch_lightness_process_pixels_linear (gfloat                *in,
+                                                    gfloat                *layer,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc,
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode)
 {
-  static const Babl *from_fish_laba = NULL;
-  static const Babl *from_fish_la = NULL;
-  static const Babl *to_fish = NULL;
-  
-  if (!from_fish_laba)
-    from_fish_laba  = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
-  if (!from_fish_la)
-    from_fish_la =  babl_fish ("R'G'B'A float", "CIE L alpha float");
-  if (!to_fish)
-     to_fish = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
-
-
-  lightness_pre_process (from_fish_la, from_fish_laba, to_fish, in, layer, out, samples);
-  gimp_operation_layer_composite (in, layer, mask, out, opacity, samples);
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_lch_lightness);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationlchlightness.h 
b/app/operations/layer-modes/gimpoperationlchlightness.h
index 7af7797..7191253 100644
--- a/app/operations/layer-modes/gimpoperationlchlightness.h
+++ b/app/operations/layer-modes/gimpoperationlchlightness.h
@@ -51,23 +51,29 @@ struct _GimpOperationLchLightnessClass
 
 GType    gimp_operation_lch_lightness_get_type              (void) G_GNUC_CONST;
 
-gboolean gimp_operation_lch_lightness_process_pixels_linear (gfloat              *in,
-                                                             gfloat              *layer,
-                                                             gfloat              *mask,
-                                                             gfloat              *out,
-                                                             gfloat               opacity,
-                                                             glong                samples,
-                                                             const GeglRectangle *roi,
-                                                             gint                 level);
+gboolean gimp_operation_lch_lightness_process_pixels_linear (gfloat                *in,
+                                                             gfloat                *layer,
+                                                             gfloat                *mask,
+                                                             gfloat                *out,
+                                                             gfloat                 opacity,
+                                                             glong                  samples,
+                                                             const GeglRectangle   *roi,
+                                                             gint                   level,
+                                                             GimpLayerBlendTRC      blend_trc, 
+                                                             GimpLayerBlendTRC      composite_trc,
+                                                             GimpLayerCompositeMode composite_mode);
 
-gboolean gimp_operation_lch_lightness_process_pixels        (gfloat              *in,
-                                                             gfloat              *layer,
-                                                             gfloat              *mask,
-                                                             gfloat              *out,
-                                                             gfloat               opacity,
-                                                             glong                samples,
-                                                             const GeglRectangle *roi,
-                                                             gint                 level);
+gboolean gimp_operation_lch_lightness_process_pixels        (gfloat                *in,
+                                                             gfloat                *layer,
+                                                             gfloat                *mask,
+                                                             gfloat                *out,
+                                                             gfloat                 opacity,
+                                                             glong                  samples,
+                                                             const GeglRectangle   *roi,
+                                                             gint                   level,
+                                                             GimpLayerBlendTRC      blend_trc, 
+                                                             GimpLayerBlendTRC      composite_trc,
+                                                             GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_LCH_LIGHTNESS_H__ */
diff --git a/app/operations/layer-modes/gimpoperationlightenonly.c 
b/app/operations/layer-modes/gimpoperationlightenonly.c
index a0fff11..b2c09f1 100644
--- a/app/operations/layer-modes/gimpoperationlightenonly.c
+++ b/app/operations/layer-modes/gimpoperationlightenonly.c
@@ -27,16 +27,17 @@
 #include "../operations-types.h"
 
 #include "gimpoperationlightenonly.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_lighten_only_process (GeglOperation       *operation,
-                                                          void                *in_buf,
-                                                          void                *aux_buf,
-                                                          void                *aux2_buf,
-                                                          void                *out_buf,
-                                                          glong                samples,
-                                                          const GeglRectangle *roi,
-                                                          gint                 level);
+                                                     void                *in_buf,
+                                                     void                *aux_buf,
+                                                     void                *aux2_buf,
+                                                     void                *out_buf,
+                                                     glong                samples,
+                                                     const GeglRectangle *roi,
+                                                     gint                 level);
 
 
 G_DEFINE_TYPE (GimpOperationLightenOnly, gimp_operation_lighten_only,
@@ -75,61 +76,25 @@ gimp_operation_lighten_only_process (GeglOperation       *operation,
                                      const GeglRectangle *roi,
                                      gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_lighten_only_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+  return gimp_operation_lighten_only_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, 
layer_mode->opacity, samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, 
layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_lighten_only_process_pixels (gfloat              *in,
-                                            gfloat              *layer,
-                                            gfloat              *mask,
-                                            gfloat              *out,
-                                            gfloat               opacity,
-                                            glong                samples,
-                                            const GeglRectangle *roi,
-                                            gint                 level)
+gimp_operation_lighten_only_process_pixels (gfloat                *in,
+                                            gfloat                *layer,
+                                            gfloat                *mask,
+                                            gfloat                *out,
+                                            gfloat                 opacity,
+                                            glong                  samples,
+                                            const GeglRectangle   *roi,
+                                            gint                   level,
+                                            GimpLayerBlendTRC      blend_trc,
+                                            GimpLayerBlendTRC      composite_trc,
+                                            GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = MAX (layer[b], in[b]);
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_lighten_only);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationlightenonly.h 
b/app/operations/layer-modes/gimpoperationlightenonly.h
index 6e4cea6..cda7443 100644
--- a/app/operations/layer-modes/gimpoperationlightenonly.h
+++ b/app/operations/layer-modes/gimpoperationlightenonly.h
@@ -50,14 +50,17 @@ struct _GimpOperationLightenOnlyClass
 
 GType    gimp_operation_lighten_only_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_lighten_only_process_pixels (gfloat              *in,
-                                                     gfloat              *layer,
-                                                     gfloat              *mask,
-                                                     gfloat              *out,
-                                                     gfloat               opacity,
-                                                     glong                samples,
-                                                     const GeglRectangle *roi,
-                                                     gint                 level);
+gboolean gimp_operation_lighten_only_process_pixels (gfloat                *in,
+                                                     gfloat                *layer,
+                                                     gfloat                *mask,
+                                                     gfloat                *out,
+                                                     gfloat                 opacity,
+                                                     glong                  samples,
+                                                     const GeglRectangle   *roi,
+                                                     gint                   level,
+                                                     GimpLayerBlendTRC      blend_trc, 
+                                                     GimpLayerBlendTRC      composite_trc,
+                                                     GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_LIGHTEN_ONLY_H__ */
diff --git a/app/operations/layer-modes/gimpoperationmultiply.c 
b/app/operations/layer-modes/gimpoperationmultiply.c
index 4c77376..2ae56e1 100644
--- a/app/operations/layer-modes/gimpoperationmultiply.c
+++ b/app/operations/layer-modes/gimpoperationmultiply.c
@@ -27,6 +27,7 @@
 #include "operations/operations-types.h"
 
 #include "gimpoperationmultiply.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_multiply_process (GeglOperation       *operation,
@@ -75,60 +76,25 @@ gimp_operation_multiply_process (GeglOperation       *operation,
                                  const GeglRectangle *roi,
                                  gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_multiply_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_multiply_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_multiply_process_pixels (gfloat              *in,
-                                        gfloat              *layer,
-                                        gfloat              *mask,
-                                        gfloat              *out,
-                                        gfloat               opacity,
-                                        glong                samples,
-                                        const GeglRectangle *roi,
-                                        gint                 level)
+gimp_operation_multiply_process_pixels (gfloat                *in,
+                                        gfloat                *layer,
+                                        gfloat                *mask,
+                                        gfloat                *out,
+                                        gfloat                 opacity,
+                                        glong                  samples,
+                                        const GeglRectangle   *roi,
+                                        gint                   level,
+                                        GimpLayerBlendTRC      blend_trc,
+                                        GimpLayerBlendTRC      composite_trc,
+                                        GimpLayerCompositeMode composite_mode)
 {
-  const gboolean  has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = layer[b] * in[b];
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_multiply);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationmultiply.h 
b/app/operations/layer-modes/gimpoperationmultiply.h
index 4417e84..e6fbbf7 100644
--- a/app/operations/layer-modes/gimpoperationmultiply.h
+++ b/app/operations/layer-modes/gimpoperationmultiply.h
@@ -50,14 +50,17 @@ struct _GimpOperationMultiplyClass
 
 GType    gimp_operation_multiply_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_multiply_process_pixels (gfloat              *in,
-                                                 gfloat              *layer,
-                                                 gfloat              *mask,
-                                                 gfloat              *out,
-                                                 gfloat               opacity,
-                                                 glong                samples,
-                                                 const GeglRectangle *roi,
-                                                 gint                 level);
+gboolean gimp_operation_multiply_process_pixels (gfloat                *in,
+                                                 gfloat                *layer,
+                                                 gfloat                *mask,
+                                                 gfloat                *out,
+                                                 gfloat                 opacity,
+                                                 glong                  samples,
+                                                 const GeglRectangle   *roi,
+                                                 gint                   level,
+                                                 GimpLayerBlendTRC      blend_trc, 
+                                                 GimpLayerBlendTRC      composite_trc,
+                                                 GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_MULTIPLY_H__ */
diff --git a/app/operations/layer-modes/gimpoperationnormal-sse2.c 
b/app/operations/layer-modes/gimpoperationnormal-sse2.c
index de69a53..065dcc4 100644
--- a/app/operations/layer-modes/gimpoperationnormal-sse2.c
+++ b/app/operations/layer-modes/gimpoperationnormal-sse2.c
@@ -32,21 +32,26 @@
 #include <emmintrin.h>
 
 gboolean
-gimp_operation_normal_process_pixels_sse2 (gfloat              *in,
-                                           gfloat              *aux,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_normal_process_pixels_sse2 (gfloat                *in,
+                                           gfloat                *aux,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
   /* check alignment */
   if ((((uintptr_t)in) | ((uintptr_t)aux) | ((uintptr_t)out)) & 0x0F)
     {
       return gimp_operation_normal_process_pixels_core (in, aux, mask, out,
                                                         opacity, samples,
-                                                        roi, level);
+                                                        roi, level, blend_trc,
+                                                        composite_trc,
+                                                        composite_mode);
     }
   else
     {
diff --git a/app/operations/layer-modes/gimpoperationnormal-sse4.c 
b/app/operations/layer-modes/gimpoperationnormal-sse4.c
index 29e33c4..502d3a5 100644
--- a/app/operations/layer-modes/gimpoperationnormal-sse4.c
+++ b/app/operations/layer-modes/gimpoperationnormal-sse4.c
@@ -32,21 +32,26 @@
 #include <smmintrin.h>
 
 gboolean
-gimp_operation_normal_process_pixels_sse4 (gfloat              *in,
-                                           gfloat              *aux,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_normal_process_pixels_sse4 (gfloat                *in,
+                                           gfloat                *aux,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
   /* check alignment */
   if ((((uintptr_t)in) | ((uintptr_t)aux) | ((uintptr_t)out)) & 0x0F)
     {
       return gimp_operation_normal_process_pixels_core (in, aux, mask, out,
                                                         opacity, samples,
-                                                        roi, level);
+                                                        roi, level, blend_trc,
+                                                        composite_trc,
+                                                        composite_mode);
     }
   else
     {
diff --git a/app/operations/layer-modes/gimpoperationnormal.c 
b/app/operations/layer-modes/gimpoperationnormal.c
index e492000..da9f5d4 100644
--- a/app/operations/layer-modes/gimpoperationnormal.c
+++ b/app/operations/layer-modes/gimpoperationnormal.c
@@ -173,20 +173,22 @@ gimp_operation_normal_process (GeglOperation       *operation,
                                const GeglRectangle *roi,
                                gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_normal_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_normal_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_normal_process_pixels_core (gfloat              *in,
-                                           gfloat              *aux,
-                                           gfloat              *mask,
-                                           gfloat              *out,
-                                           gfloat               opacity,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_normal_process_pixels_core (gfloat                *in,
+                                           gfloat                *aux,
+                                           gfloat                *mask,
+                                           gfloat                *out,
+                                           gfloat                 opacity,
+                                           glong                  samples,
+                                           const GeglRectangle   *roi,
+                                           gint                   level,
+                                           GimpLayerBlendTRC      blend_trc,
+                                           GimpLayerBlendTRC      composite_trc,
+                                           GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes/gimpoperationnormal.h 
b/app/operations/layer-modes/gimpoperationnormal.h
index 1b8e401..5a96e15 100644
--- a/app/operations/layer-modes/gimpoperationnormal.h
+++ b/app/operations/layer-modes/gimpoperationnormal.h
@@ -51,32 +51,41 @@ GType    gimp_operation_normal_get_type            (void) G_GNUC_CONST;
 
 extern GimpLayerModeFunc gimp_operation_normal_process_pixels;
 
-gboolean gimp_operation_normal_process_pixels_core (gfloat              *in,
-                                                    gfloat              *aux,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
-
-gboolean gimp_operation_normal_process_pixels_sse2 (gfloat              *in,
-                                                    gfloat              *aux,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
-
-gboolean gimp_operation_normal_process_pixels_sse4 (gfloat              *in,
-                                                    gfloat              *aux,
-                                                    gfloat              *mask,
-                                                    gfloat              *out,
-                                                    gfloat               opacity,
-                                                    glong                samples,
-                                                    const GeglRectangle *roi,
-                                                    gint                 level);
+gboolean gimp_operation_normal_process_pixels_core (gfloat                *in,
+                                                    gfloat                *aux,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
+
+gboolean gimp_operation_normal_process_pixels_sse2 (gfloat                *in,
+                                                    gfloat                *aux,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
+
+gboolean gimp_operation_normal_process_pixels_sse4 (gfloat                *in,
+                                                    gfloat                *aux,
+                                                    gfloat                *mask,
+                                                    gfloat                *out,
+                                                    gfloat                 opacity,
+                                                    glong                  samples,
+                                                    const GeglRectangle   *roi,
+                                                    gint                   level,
+                                                    GimpLayerBlendTRC      blend_trc, 
+                                                    GimpLayerBlendTRC      composite_trc,
+                                                    GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_NORMAL_H__ */
diff --git a/app/operations/layer-modes/gimpoperationoverlay.c 
b/app/operations/layer-modes/gimpoperationoverlay.c
index ca67587..b3d551c 100644
--- a/app/operations/layer-modes/gimpoperationoverlay.c
+++ b/app/operations/layer-modes/gimpoperationoverlay.c
@@ -26,6 +26,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationoverlay.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_overlay_process (GeglOperation       *operation,
@@ -74,69 +75,26 @@ gimp_operation_overlay_process (GeglOperation       *operation,
                                 const GeglRectangle *roi,
                                 gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_overlay_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_overlay_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_overlay_process_pixels (gfloat              *in,
-                                       gfloat              *layer,
-                                       gfloat              *mask,
-                                       gfloat              *out,
-                                       gfloat               opacity,
-                                       glong                samples,
-                                       const GeglRectangle *roi,
-                                       gint                 level)
+gimp_operation_overlay_process_pixels (gfloat                *in,
+                                       gfloat                *layer,
+                                       gfloat                *mask,
+                                       gfloat                *out,
+                                       gfloat                 opacity,
+                                       glong                  samples,
+                                       const GeglRectangle   *roi,
+                                       gint                   level,
+                                       GimpLayerBlendTRC      blend_trc,
+                                       GimpLayerBlendTRC      composite_trc,
+                                       GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha, new_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
-
-      if (comp_alpha && new_alpha)
-        {
-          gint   b;
-          gfloat ratio = comp_alpha / new_alpha;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp;
-
-              if (in[b] < 0.5)
-                comp = 2.0 * in[b] * layer[b];
-              else
-                comp = 1.0 - 2.0 * (1.0 - layer[b]) * (1.0 - in[b]);
-
-              out[b] = comp * ratio + in[b] * (1.0 - ratio);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_overlay);
   return TRUE;
 }
+
diff --git a/app/operations/layer-modes/gimpoperationoverlay.h 
b/app/operations/layer-modes/gimpoperationoverlay.h
index d31f01d..57001b8 100644
--- a/app/operations/layer-modes/gimpoperationoverlay.h
+++ b/app/operations/layer-modes/gimpoperationoverlay.h
@@ -49,14 +49,17 @@ struct _GimpOperationOverlayClass
 
 GType    gimp_operation_overlay_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_overlay_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level);
+gboolean gimp_operation_overlay_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc, 
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_OVERLAY_H__ */
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.c 
b/app/operations/layer-modes/gimpoperationpointlayermode.c
index 419f1c1..8e47edf 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.c
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.c
@@ -21,8 +21,8 @@
 
 #include "config.h"
 
-#include <cairo.h>
 #include <gegl-plugin.h>
+#include <cairo.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #include "libgimpcolor/gimpcolor.h"
@@ -66,6 +66,13 @@ G_DEFINE_TYPE (GimpOperationPointLayerMode, gimp_operation_point_layer_mode,
 #define parent_class gimp_operation_point_layer_mode_parent_class
 
 
+const Babl *_gimp_fish_rgba_to_perceptual = NULL;
+const Babl *_gimp_fish_perceptual_to_rgba = NULL;
+const Babl *_gimp_fish_perceptual_to_laba = NULL;
+const Babl *_gimp_fish_rgba_to_laba = NULL;
+const Babl *_gimp_fish_laba_to_rgba = NULL;
+const Babl *_gimp_fish_laba_to_perceptual = NULL;
+
 static void
 gimp_operation_point_layer_mode_class_init (GimpOperationPointLayerModeClass *klass)
 {
@@ -117,6 +124,15 @@ gimp_operation_point_layer_mode_class_init (GimpOperationPointLayerModeClass *kl
                                                       GIMP_PARAM_READWRITE |
                                                       G_PARAM_CONSTRUCT));
 
+  if (_gimp_fish_rgba_to_perceptual == NULL)
+  {
+    _gimp_fish_rgba_to_perceptual = babl_fish ("RGBA float", "R'G'B'A float");
+    _gimp_fish_perceptual_to_rgba = babl_fish ("R'G'B'A float", "RGBA float");
+    _gimp_fish_perceptual_to_laba = babl_fish ("R'G'B'A float", "CIE Lab alpha float");
+    _gimp_fish_rgba_to_laba = babl_fish ("RGBA float", "CIE Lab alpha float");
+    _gimp_fish_laba_to_rgba = babl_fish ("CIE Lab alpha float", "RGBA float");
+    _gimp_fish_laba_to_perceptual = babl_fish ("CIE Lab alpha float", "R'G'B'A float");
+  }
 }
 
 static void
diff --git a/app/operations/layer-modes/gimpoperationpointlayermode.h 
b/app/operations/layer-modes/gimpoperationpointlayermode.h
index 630e060..93cc9ab 100644
--- a/app/operations/layer-modes/gimpoperationpointlayermode.h
+++ b/app/operations/layer-modes/gimpoperationpointlayermode.h
@@ -23,7 +23,13 @@
 
 
 #include <gegl-plugin.h>
-
+#include <math.h>
+#include <alloca.h>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "../operations-enums.h"
+#include "../operations-types.h"
+#include "libgimpcolor/gimpcolor.h"
 
 #define GIMP_TYPE_OPERATION_POINT_LAYER_MODE            (gimp_operation_point_layer_mode_get_type ())
 #define GIMP_OPERATION_POINT_LAYER_MODE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GIMP_TYPE_OPERATION_POINT_LAYER_MODE, GimpOperationPointLayerMode))
@@ -51,46 +57,9 @@ struct _GimpOperationPointLayerMode
   GimpLayerCompositeMode       composite_mode;
 };
 
-
 GType   gimp_operation_point_layer_mode_get_type (void) G_GNUC_CONST;
 
-
-static inline void
-gimp_operation_layer_composite (const gfloat *in,
-                                const gfloat *layer,
-                                const gfloat *mask,
-                                gfloat       *out,
-                                gfloat        opacity,
-                                glong         samples)
-{
-  while (samples--)
-    {
-      gfloat comp_alpha = layer[ALPHA] * opacity;
-      if (mask)
-        comp_alpha *= *mask++;
-      if (comp_alpha != 0.0f)
-        {
-          out[RED]   = out[RED]   * comp_alpha + in[RED]   * (1.0f - comp_alpha);
-          out[GREEN] = out[GREEN] * comp_alpha + in[GREEN] * (1.0f - comp_alpha);
-          out[BLUE]  = out[BLUE]  * comp_alpha + in[BLUE]  * (1.0f - comp_alpha);
-        }
-      else
-        {
-          gint b;
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-    }
-}
-
+#include "gimpoperationnormal.h"
 
 
 #endif /* __GIMP_OPERATION_POINT_LAYER_MODE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationreplace.c 
b/app/operations/layer-modes/gimpoperationreplace.c
index 93c895b..12450ce 100644
--- a/app/operations/layer-modes/gimpoperationreplace.c
+++ b/app/operations/layer-modes/gimpoperationreplace.c
@@ -73,20 +73,23 @@ gimp_operation_replace_process (GeglOperation       *operation,
                                 const GeglRectangle *roi,
                                 gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_replace_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_replace_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_replace_process_pixels (gfloat              *in,
-                                       gfloat              *layer,
-                                       gfloat              *mask,
-                                       gfloat              *out,
-                                       gfloat               opacity,
-                                       glong                samples,
-                                       const GeglRectangle *roi,
-                                       gint                 level)
+gimp_operation_replace_process_pixels (gfloat                *in,
+                                       gfloat                *layer,
+                                       gfloat                *mask,
+                                       gfloat                *out,
+                                       gfloat                 opacity,
+                                       glong                  samples,
+                                       const GeglRectangle   *roi,
+                                       gint                   level,
+                                       GimpLayerBlendTRC      blend_trc,
+                                       GimpLayerBlendTRC      composite_trc,
+                                       GimpLayerCompositeMode composite_mode)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/layer-modes/gimpoperationreplace.h 
b/app/operations/layer-modes/gimpoperationreplace.h
index 5747bcb..ad34751 100644
--- a/app/operations/layer-modes/gimpoperationreplace.h
+++ b/app/operations/layer-modes/gimpoperationreplace.h
@@ -49,14 +49,17 @@ struct _GimpOperationReplaceClass
 
 GType    gimp_operation_replace_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_replace_process_pixels (gfloat              *in,
-                                                gfloat              *layer,
-                                                gfloat              *mask,
-                                                gfloat              *out,
-                                                gfloat               opacity,
-                                                glong                samples,
-                                                const GeglRectangle *roi,
-                                                gint                 level);
+gboolean gimp_operation_replace_process_pixels (gfloat                *in,
+                                                gfloat                *layer,
+                                                gfloat                *mask,
+                                                gfloat                *out,
+                                                gfloat                 opacity,
+                                                glong                  samples,
+                                                const GeglRectangle   *roi,
+                                                gint                   level,
+                                                GimpLayerBlendTRC      blend_trc, 
+                                                GimpLayerBlendTRC      composite_trc,
+                                                GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_REPLACE_H__ */
diff --git a/app/operations/layer-modes/gimpoperationscreen.c 
b/app/operations/layer-modes/gimpoperationscreen.c
index d2622c9..76ac125 100644
--- a/app/operations/layer-modes/gimpoperationscreen.c
+++ b/app/operations/layer-modes/gimpoperationscreen.c
@@ -27,6 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationscreen.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_screen_process (GeglOperation       *operation,
@@ -65,6 +66,7 @@ gimp_operation_screen_init (GimpOperationScreen *self)
 {
 }
 
+
 static gboolean
 gimp_operation_screen_process (GeglOperation       *operation,
                                void                *in_buf,
@@ -75,61 +77,25 @@ gimp_operation_screen_process (GeglOperation       *operation,
                                const GeglRectangle *roi,
                                gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_screen_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_screen_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_screen_process_pixels (gfloat              *in,
-                                      gfloat              *layer,
-                                      gfloat              *mask,
-                                      gfloat              *out,
-                                      gfloat               opacity,
-                                      glong                samples,
-                                      const GeglRectangle *roi,
-                                      gint                 level)
+gimp_operation_screen_process_pixels (gfloat                *in,
+                                      gfloat                *layer,
+                                      gfloat                *mask,
+                                      gfloat                *out,
+                                      gfloat                 opacity,
+                                      glong                  samples,
+                                      const GeglRectangle   *roi,
+                                      gint                   level,
+                                      GimpLayerBlendTRC      blend_trc,
+                                      GimpLayerBlendTRC      composite_trc,
+                                      GimpLayerCompositeMode composite_mode)
 {
-  const gboolean  has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = 1.0 - (1.0 - in[b]) * (1.0 - layer[b]);
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+               blend_trc, composite_trc, composite_mode, blendfun_screen);
   return TRUE;
 }
+
diff --git a/app/operations/layer-modes/gimpoperationscreen.h 
b/app/operations/layer-modes/gimpoperationscreen.h
index 200f679..2de2110 100644
--- a/app/operations/layer-modes/gimpoperationscreen.h
+++ b/app/operations/layer-modes/gimpoperationscreen.h
@@ -49,14 +49,17 @@ struct _GimpOperationScreenClass
 
 GType    gimp_operation_screen_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_screen_process_pixels (gfloat              *in,
-                                               gfloat              *layer,
-                                               gfloat              *mask,
-                                               gfloat              *out,
-                                               gfloat               opacity,
-                                               glong                samples,
-                                               const GeglRectangle *roi,
-                                               gint                 level);
+gboolean gimp_operation_screen_process_pixels (gfloat                *in,
+                                               gfloat                *layer,
+                                               gfloat                *mask,
+                                               gfloat                *out,
+                                               gfloat                 opacity,
+                                               glong                  samples,
+                                               const GeglRectangle   *roi,
+                                               gint                   level,
+                                               GimpLayerBlendTRC      blend_trc, 
+                                               GimpLayerBlendTRC      composite_trc,
+                                               GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_SCREEN_H__ */
diff --git a/app/operations/layer-modes/gimpoperationsoftlight.c 
b/app/operations/layer-modes/gimpoperationsoftlight.c
index 74b3ea1..9d7f06f 100644
--- a/app/operations/layer-modes/gimpoperationsoftlight.c
+++ b/app/operations/layer-modes/gimpoperationsoftlight.c
@@ -26,16 +26,17 @@
 #include "../operations-types.h"
 
 #include "gimpoperationsoftlight.h"
+#include "gimpblendcomposite.h"
 
 
 static gboolean gimp_operation_softlight_process (GeglOperation       *operation,
-                                                       void                *in_buf,
-                                                       void                *aux_buf,
-                                                       void                *aux2_buf,
-                                                       void                *out_buf,
-                                                       glong                samples,
-                                                       const GeglRectangle *roi,
-                                                       gint                 level);
+                                                  void                *in_buf,
+                                                  void                *aux_buf,
+                                                  void                *aux2_buf,
+                                                  void                *out_buf,
+                                                  glong                samples,
+                                                  const GeglRectangle *roi,
+                                                  gint                 level);
 
 
 G_DEFINE_TYPE (GimpOperationSoftlight, gimp_operation_softlight,
@@ -92,75 +93,24 @@ gimp_operation_softlight_process (GeglOperation       *operation,
                                   const GeglRectangle *roi,
                                   gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
-
-  return gimp_operation_softlight_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
+  return gimp_operation_softlight_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_softlight_process_pixels (gfloat              *in,
-                                         gfloat              *layer,
-                                         gfloat              *mask,
-                                         gfloat              *out,
-                                         gfloat               opacity,
-                                         glong                samples,
-                                         const GeglRectangle *roi,
-                                         gint                 level)
+gimp_operation_softlight_process_pixels (gfloat                *in,
+                                         gfloat                *layer,
+                                         gfloat                *mask,
+                                         gfloat                *out,
+                                         gfloat                 opacity,
+                                         glong                  samples,
+                                         const GeglRectangle   *roi,
+                                         gint                   level,
+                                         GimpLayerBlendTRC      blend_trc,
+                                         GimpLayerBlendTRC      composite_trc,
+                                         GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0f)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-#if 0
-              /* softlight is now used for what GIMP formerly called
-               * OVERLAY.  We fixed OVERLAY to use the right math
-               * (under the name NEW_OVERLAY), and redirect uses of
-               * the old OVERLAY blend mode here. This math was
-               * formerly used for OVERLAY and is exactly the same as
-               * the multiply, screen, comp math used below.
-               * See bug #673501.
-               */
-              gfloat comp = in[b] * (in[b] + (2.0 * layer[b]) * (1.0 - in[b]));
-#endif
-
-              gfloat multiply = in[b] * layer[b];
-              gfloat screen   = 1.0 - (1.0 - in[b]) * (1.0 - layer[b]);
-              gfloat comp     = (1.0 - in[b]) * multiply + in[b] * screen;
-
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask ++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples,
+     blend_trc, composite_trc, composite_mode, blendfun_softlight);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationsoftlight.h 
b/app/operations/layer-modes/gimpoperationsoftlight.h
index 9456095..cb0e085 100644
--- a/app/operations/layer-modes/gimpoperationsoftlight.h
+++ b/app/operations/layer-modes/gimpoperationsoftlight.h
@@ -49,14 +49,16 @@ struct _GimpOperationSoftlightClass
 
 GType    gimp_operation_softlight_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_softlight_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level);
-
+gboolean gimp_operation_softlight_process_pixels (gfloat                *in,
+                                                  gfloat                *layer,
+                                                  gfloat                *mask,
+                                                  gfloat                *out,
+                                                  gfloat                 opacity,
+                                                  glong                  samples,
+                                                  const GeglRectangle   *roi,
+                                                  gint                   level,
+                                                  GimpLayerBlendTRC      blend_trc, 
+                                                  GimpLayerBlendTRC      composite_trc,
+                                                  GimpLayerCompositeMode composite_mode);
 
 #endif /* __GIMP_OPERATION_SOFTLIGHT_H__ */
diff --git a/app/operations/layer-modes/gimpoperationsubtract.c 
b/app/operations/layer-modes/gimpoperationsubtract.c
index 6fbc5e4..b2b696d 100644
--- a/app/operations/layer-modes/gimpoperationsubtract.c
+++ b/app/operations/layer-modes/gimpoperationsubtract.c
@@ -27,7 +27,7 @@
 #include "../operations-types.h"
 
 #include "gimpoperationsubtract.h"
-
+#include "gimpblendcomposite.h"
 
 static gboolean gimp_operation_subtract_process (GeglOperation       *operation,
                                                  void                *in_buf,
@@ -75,60 +75,25 @@ gimp_operation_subtract_process (GeglOperation       *operation,
                                  const GeglRectangle *roi,
                                  gint                 level)
 {
-  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+  GimpOperationPointLayerMode *layer_mode = (GimpOperationPointLayerMode*)operation;
 
-  return gimp_operation_subtract_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+  return gimp_operation_subtract_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, layer_mode->opacity, 
samples, roi, level, layer_mode->blend_trc, layer_mode->composite_trc, layer_mode->composite_mode);
 }
 
 gboolean
-gimp_operation_subtract_process_pixels (gfloat              *in,
-                                        gfloat              *layer,
-                                        gfloat              *mask,
-                                        gfloat              *out,
-                                        gfloat               opacity,
-                                        glong                samples,
-                                        const GeglRectangle *roi,
-                                        gint                 level)
+gimp_operation_subtract_process_pixels (gfloat                *in,
+                                        gfloat                *layer,
+                                        gfloat                *mask,
+                                        gfloat                *out,
+                                        gfloat                 opacity,
+                                        glong                  samples,
+                                        const GeglRectangle   *roi,
+                                        gint                   level,
+                                        GimpLayerBlendTRC      blend_trc,
+                                        GimpLayerBlendTRC      composite_trc,
+                                        GimpLayerCompositeMode composite_mode)
 {
-  const gboolean has_mask = mask != NULL;
-
-  while (samples--)
-    {
-      gfloat comp_alpha;
-
-      comp_alpha = layer[ALPHA] * opacity;
-      if (has_mask)
-        comp_alpha *= *mask;
-
-      if (comp_alpha != 0.0)
-        {
-          gint   b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              gfloat comp = in[b] - layer[b];
-              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
-            }
-        }
-      else
-        {
-          gint b;
-
-          for (b = RED; b < ALPHA; b++)
-            {
-              out[b] = in[b];
-            }
-        }
-
-      out[ALPHA] = in[ALPHA];
-
-      in    += 4;
-      layer += 4;
-      out   += 4;
-
-      if (has_mask)
-        mask++;
-    }
-
+  gimp_composite_blend (in, layer, mask, out, opacity, samples, blend_trc,
+                        composite_trc, composite_mode, blendfun_subtract);
   return TRUE;
 }
diff --git a/app/operations/layer-modes/gimpoperationsubtract.h 
b/app/operations/layer-modes/gimpoperationsubtract.h
index 23c656a..bb9c49b 100644
--- a/app/operations/layer-modes/gimpoperationsubtract.h
+++ b/app/operations/layer-modes/gimpoperationsubtract.h
@@ -50,14 +50,17 @@ struct _GimpOperationSubtractClass
 
 GType    gimp_operation_subtract_get_type       (void) G_GNUC_CONST;
 
-gboolean gimp_operation_subtract_process_pixels (gfloat              *in,
-                                                 gfloat              *layer,
-                                                 gfloat              *mask,
-                                                 gfloat              *out,
-                                                 gfloat               opacity,
-                                                 glong                samples,
-                                                 const GeglRectangle *roi,
-                                                 gint                 level);
+gboolean gimp_operation_subtract_process_pixels (gfloat                *in,
+                                                 gfloat                *layer,
+                                                 gfloat                *mask,
+                                                 gfloat                *out,
+                                                 gfloat                 opacity,
+                                                 glong                  samples,
+                                                 const GeglRectangle   *roi,
+                                                 gint                   level,
+                                                 GimpLayerBlendTRC      blend_trc, 
+                                                 GimpLayerBlendTRC      composite_trc,
+                                                 GimpLayerCompositeMode composite_mode);
 
 
 #endif /* __GIMP_OPERATION_SUBTRACT_H__ */
diff --git a/app/operations/operations-types.h b/app/operations/operations-types.h
index ad5088d..8068d07 100644
--- a/app/operations/operations-types.h
+++ b/app/operations/operations-types.h
@@ -55,14 +55,17 @@ typedef struct _GimpCagePoint                   GimpCagePoint;
 
 /*  functions  */
 
-typedef gboolean (* GimpLayerModeFunc) (gfloat              *in,
-                                        gfloat              *aux,
-                                        gfloat              *mask,
-                                        gfloat              *out,
-                                        gfloat               opacity,
-                                        glong                samples,
-                                        const GeglRectangle *roi,
-                                        gint                 level);
+typedef gboolean (* GimpLayerModeFunc) (gfloat                *in,
+                                        gfloat                *aux,
+                                        gfloat                *mask,
+                                        gfloat                *out,
+                                        gfloat                 opacity,
+                                        glong                  samples,
+                                        const GeglRectangle   *roi,
+                                        gint                   level,
+                                        GimpLayerBlendTRC      blend_trc,
+                                        GimpLayerBlendTRC      composite_trc,
+                                        GimpLayerCompositeMode composite_mode);
 
 typedef  void    (* GimpBlendFunc)     (const float         *dest,
                                         const float         *src,
diff --git a/app/paint/gimppaintcore-loops.c b/app/paint/gimppaintcore-loops.c
index 8ab5e27..fe07232 100644
--- a/app/paint/gimppaintcore-loops.c
+++ b/app/paint/gimppaintcore-loops.c
@@ -297,6 +297,9 @@ do_layer_blend (GeglBuffer    *src_buffer,
                 gboolean       linear_mode,
                 GimpLayerMode  paint_mode)
 {
+  GimpLayerBlendTRC   blend_trc = GIMP_LAYER_BLEND_RGB_PERCEPTUAL;//XXX
+  GimpLayerBlendTRC   composite_trc = GIMP_LAYER_BLEND_RGB_LINEAR;//placeholders
+  GimpLayerCompositeMode composite_mode = GIMP_LAYER_COMPOSITE_SRC_OVER;//placeholders
   GeglRectangle       roi;
   GeglRectangle       mask_roi;
   GeglRectangle       process_roi;
@@ -366,7 +369,10 @@ do_layer_blend (GeglBuffer    *src_buffer,
                          opacity,
                          iter->roi[0].width,
                          &process_roi,
-                         0);
+                         0,
+                         blend_trc,
+                         composite_trc,
+                         composite_mode);
 
           in_pixel    += iter->roi[0].width * 4;
           out_pixel   += iter->roi[0].width * 4;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]