package de.lessvoid.nifty.render.batch.core;

import java.nio.IntBuffer;

import javax.annotation.Nonnull;

import de.lessvoid.nifty.render.batch.CheckGL;
import de.lessvoid.nifty.render.batch.spi.BufferFactory;
import de.lessvoid.nifty.render.batch.spi.core.CoreGL;

/**
 * @author void
 * @author Aaron Mahan &lt;aaron@forerunnergames.com&gt;
 *
 * Note: Requires OpenGL 3.2 or greater.
 */
public class CoreProfileSaveGLState {
  @Nonnull
  private final CoreGL gl;
  @Nonnull
  private final IntBuffer params;
  private int currentProgram;
  private int textureBinding;
  private int activeTexture;
  private int samplerBindingTex0;
  private boolean blending;
  private int blendingSrcFactor;
  private int blendingDstFactor;
  private boolean primitiveRestart;
  private int primitiveRestartIndex;

  public CoreProfileSaveGLState(@Nonnull final CoreGL gl, @Nonnull final BufferFactory bufferFactory) {
    this.gl = gl;
    params = bufferFactory.createNativeOrderedIntBuffer(16);
  }

  public void saveCore() {
  	// Store currently bound program.
    params.clear();
    gl.glGetIntegerv(gl.GL_CURRENT_PROGRAM(), params);
    currentProgram = params.get(0);

    // Store currently active texture unit.
    params.clear();
    gl.glGetIntegerv(gl.GL_ACTIVE_TEXTURE(), params);
    activeTexture = params.get(0);

    // This texture unit will be used by Nifty.
    gl.glActiveTexture(gl.GL_TEXTURE0());

    // Store sampler bound to it.
    params.clear();
    gl.glGetIntegerv(gl.GL_SAMPLER_BINDING(), params);
    samplerBindingTex0 = params.get(0);
    
    // Now unbind sampler so it doesn't overrides texture filtering.
    gl.glBindSampler(0, 0);

    // Store texture bound to 2D target.
    params.clear();
    gl.glGetIntegerv(gl.GL_TEXTURE_BINDING_2D(), params);
    textureBinding = params.get(0);

    // Store blending state.
    blending = gl.glIsEnabled(gl.GL_BLEND());

    // Store blending source parameter.
    params.clear();
    gl.glGetIntegerv(gl.GL_BLEND_SRC(), params);
    blendingSrcFactor = params.get(0);

    // Store blending destination parameter.
    params.clear();
    gl.glGetIntegerv(gl.GL_BLEND_DST(), params);
    blendingDstFactor = params.get(0);

    // Store primitive restart state.
    primitiveRestart = gl.glIsEnabled(gl.GL_PRIMITIVE_RESTART());

    // Store primitive restart index.
    params.clear();
    gl.glGetIntegerv(gl.GL_PRIMITIVE_RESTART_INDEX(), params);
    primitiveRestartIndex = params.get(0);

    CheckGL.checkGLError(gl, "Failed to save OpenGL Core Profile state!", true);
  }

  public void restoreCore() {
  	// Restore program.
    gl.glUseProgram(currentProgram);
    // Restore sampler that was bound to texture unit 0.
    gl.glBindSampler(0, samplerBindingTex0);
    // Restore active texture unit.
    gl.glActiveTexture(activeTexture);
    // Restore bound texture to 2D target.
    gl.glBindTexture(gl.GL_TEXTURE_2D(), textureBinding);
    // Restore blending state.
    enable(gl.GL_BLEND(), blending);
    // Restore blending functions.
    gl.glBlendFunc(blendingSrcFactor, blendingDstFactor);
    // Restore primitive restart state.
    enable(gl.GL_PRIMITIVE_RESTART(), primitiveRestart);
    // Restore primitive restart index.
    gl.glPrimitiveRestartIndex(primitiveRestartIndex);

    CheckGL.checkGLError(gl, "Failed to restore OpenGL Core Profile state!", true);
  }

  private void enable(final int state, final boolean value) {
    if (value) {
      gl.glEnable(state);
    } else {
      gl.glDisable(state);
    }
  }
}

@@ -1017,45 +1017,8 @@
 ) %7B%0A
-  %09// Store currently bound program.%0A
     
@@ -1129,52 +1129,8 @@
 );%0A%0A
-    // Store currently active texture unit.%0A
     
@@ -1243,387 +1243,119 @@
     
-// This texture unit will be used by Nifty.%0A    gl.glActiveTexture(gl.GL_TEXTURE0());%0A%0A    // Store sampler bound to it.%0A    params.clear();%0A    gl.glGetIntegerv(gl.GL_SAMPLER_BINDING(), params);%0A    samplerBindingTex0 = params.get(0);%0A    %0A    // Now unbind sampler so it doesn't overrides texture filtering.%0A    gl.glBindSampler(0, 0);%0A%0A    // Store texture bound to 2D target.
+params.clear();%0A    gl.glGetIntegerv(gl.GL_SAMPLER_BINDING(), params);%0A    samplerBindingTex0 = params.get(0);%0A
 %0A   
@@ -1470,37 +1470,8 @@
 );%0A%0A
-    // Store blending state.%0A
     
@@ -1517,48 +1517,8 @@
 );%0A%0A
-    // Store blending source parameter.%0A
     
@@ -1626,53 +1626,8 @@
 );%0A%0A
-    // Store blending destination parameter.%0A
     
@@ -1735,46 +1735,8 @@
 );%0A%0A
-    // Store primitive restart state.%0A
     
@@ -1802,46 +1802,8 @@
 );%0A%0A
-    // Store primitive restart index.%0A
     
@@ -2045,31 +2045,8 @@
 ) %7B%0A
-  %09// Restore program.%0A
     
@@ -2086,223 +2086,87 @@
     
-// Restore sampler that was bound to texture unit 0.%0A    gl.glBindSampler(0, samplerBindingTex0);%0A    // Restore active texture unit.%0A    gl.glActiveTexture(activeTexture);%0A    // Restore bound texture to 2D target.
+gl.glActiveTexture(activeTexture);%0A    gl.glBindSampler(0, samplerBindingTex0);
 %0A   
@@ -2224,39 +2224,8 @@
 g);%0A
-    // Restore blending state.%0A
     
@@ -2261,43 +2261,8 @@
 g);%0A
-    // Restore blending functions.%0A
     
@@ -2319,48 +2319,8 @@
 r);%0A
-    // Restore primitive restart state.%0A
     
@@ -2376,48 +2376,8 @@
 t);%0A
-    // Restore primitive restart index.%0A
     
@@ -2427,17 +2427,16 @@
 Index);%0A
-%0A
     Chec

Revert "fix: Sampler state "