/*
 * Copyright © 2015 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jcanephora.jogl;

import com.io7m.jcanephora.core.JCGLBlendEquation;
import com.io7m.jcanephora.core.JCGLBlendFunction;
import com.io7m.jcanephora.core.JCGLException;
import com.io7m.jcanephora.core.JCGLExceptionBlendingMisconfigured;
import com.io7m.jcanephora.core.api.JCGLBlendingType;
import com.io7m.jnull.NullCheck;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL3;

final class JOGLBlending implements JCGLBlendingType
{
  private final JOGLContext context;
  private final GL3 gl;
  private boolean blend;
  private JCGLBlendEquation equation_rgb;
  private JCGLBlendEquation equation_alpha;
  private JCGLBlendFunction source_rgb_factor;
  private JCGLBlendFunction source_alpha_factor;
  private JCGLBlendFunction destination_rgb_factor;
  private JCGLBlendFunction destination_alpha_factor;

  JOGLBlending(final JOGLContext c)
  {
    this.context = NullCheck.notNull(c);
    this.gl = this.context.getGL3();
    this.blend = this.gl.glIsEnabled(GL.GL_BLEND);
    JOGLErrorChecking.checkErrors(this.gl);
  }

  @Override
  public void blendingDisable()
    throws JCGLException
  {
    if (this.blend) {
      this.gl.glDisable(GL.GL_BLEND);
      this.blend = false;
    }
  }

  @Override
  public boolean blendingIsEnabled()
    throws JCGLException
  {
    return this.blend;
  }

  @Override
  public void blendingEnableSeparateWithEquationSeparate(
    final JCGLBlendFunction in_source_rgb_factor,
    final JCGLBlendFunction in_source_alpha_factor,
    final JCGLBlendFunction in_destination_rgb_factor,
    final JCGLBlendFunction in_destination_alpha_factor,
    final JCGLBlendEquation in_equation_rgb,
    final JCGLBlendEquation in_equation_alpha)
    throws JCGLException, JCGLExceptionBlendingMisconfigured
  {
    NullCheck.notNull(in_source_rgb_factor, "Source RGB factor");
    NullCheck.notNull(in_source_alpha_factor, "Source alpha factor");
    NullCheck.notNull(in_destination_rgb_factor, "Destination RGB factor");
    NullCheck.notNull(in_destination_alpha_factor, "Destination alpha factor");
    NullCheck.notNull(in_equation_rgb, "Equation RGB");
    NullCheck.notNull(in_equation_alpha, "Equation alpha");

    if (in_destination_rgb_factor
      == JCGLBlendFunction.BLEND_SOURCE_ALPHA_SATURATE) {
      throw new JCGLExceptionBlendingMisconfigured(
        "Destination RGB factor not SOURCE_ALPHA_SATURATE");
    }
    if (in_destination_alpha_factor
      == JCGLBlendFunction.BLEND_SOURCE_ALPHA_SATURATE) {
      throw new JCGLExceptionBlendingMisconfigured(
        "Destination alpha factor not SOURCE_ALPHA_SATURATE");
    }

    if (!this.blend) {
      this.gl.glEnable(GL.GL_BLEND);
      this.blend = true;
    }

    if (this.equation_rgb != in_equation_rgb
      || this.equation_alpha != in_equation_alpha) {
      this.gl.glBlendEquationSeparate(
        JOGLTypeConversions.blendEquationToGL(in_equation_rgb),
        JOGLTypeConversions.blendEquationToGL(in_equation_alpha));
      this.equation_rgb = in_equation_rgb;
      this.equation_alpha = in_equation_alpha;
    }

    if (this.source_rgb_factor != in_source_rgb_factor
      || this.source_alpha_factor != in_source_alpha_factor
      || this.destination_rgb_factor != in_destination_rgb_factor
      || this.destination_alpha_factor != in_destination_alpha_factor) {
      this.gl.glBlendFuncSeparate(
        JOGLTypeConversions.blendFunctionToGL(in_source_rgb_factor),
        JOGLTypeConversions.blendFunctionToGL(in_destination_rgb_factor),
        JOGLTypeConversions.blendFunctionToGL(in_source_alpha_factor),
        JOGLTypeConversions.blendFunctionToGL(in_destination_alpha_factor));
      this.source_rgb_factor = in_source_rgb_factor;
      this.source_alpha_factor = in_source_alpha_factor;
      this.destination_rgb_factor = in_destination_rgb_factor;
      this.destination_alpha_factor = in_destination_alpha_factor;
    }
  }
}

@@ -1187,63 +1187,227 @@
 L3;%0A
-%0Afinal class JOGLBlending implements JCGLBlendingType%0A%7B
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0Afinal class JOGLBlending implements JCGLBlendingType%0A%7B%0A  private static final Logger LOG;%0A%0A  static %7B%0A    LOG = LoggerFactory.getLogger(JOGLBlending.class);%0A  %7D%0A
 %0A  p
@@ -2155,16 +2155,94 @@
  false;%0A
+    %7D else %7B%0A      JOGLBlending.LOG.trace(%22redundant blend disable ignored%22);%0A
     %7D%0A  
@@ -3713,24 +3713,101 @@
  true;%0A    %7D
+ else %7B%0A      JOGLBlending.LOG.trace(%22redundant blend enable ignored%22);%0A    %7D
 %0A%0A    if (th
@@ -4155,24 +4155,110 @@
 alpha;%0A    %7D
+ else %7B%0A      JOGLBlending.LOG.trace(%22redundant blend equation change ignored%22);%0A    %7D
 %0A%0A    if (th
@@ -5063,24 +5063,110 @@
 pha_factor;%0A
+    %7D else %7B%0A      JOGLBlending.LOG.trace(%22redundant blend function change ignored%22);%0A
     %7D%0A  %7D%0A%7D%0A

Add trace logs for redundant blend changes