1 /**
2  * Copyright 2013 JogAmp Community. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice, this list of
8  *       conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *       of conditions and the following disclaimer in the documentation and/or other materials
12  *       provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  * or implied, of JogAmp Community.
27  */
28 package com.jogamp.opengl.util.texture;
29 
30 import com.jogamp.opengl.GL;
31 import com.jogamp.opengl.GL2ES2;
32 import com.jogamp.opengl.GL2ES3;
33 import com.jogamp.opengl.GL2GL3;
34 import com.jogamp.opengl.GLException;
35 
36 /**
37  * Preserves a [ texture-unit, texture-target ] state.
38  * <p>
39  * The states keys are the retrieved active texture-unit and the given texture-target
40  * for which the following states are being queried:
41  * <pre>
42  *   - texture-object
43  *   - GL.GL_TEXTURE_MAG_FILTER
44  *   - GL.GL_TEXTURE_MIN_FILTER
45  *   - GL.GL_TEXTURE_WRAP_S
46  *   - GL.GL_TEXTURE_WRAP_T
47  * </pre>
48  */
49 public class TextureState {
50     /**
51      * Returns the <code>pname</code> to query the <code>textureTarget</code> currently bound to the active texture-unit.
52      * <p>
53      * Returns <code>0</code> is <code>textureTarget</code> is not supported.
54      * </p>
55      */
getTextureTargetQueryName(final int textureTarget)56     public static final int getTextureTargetQueryName(final int textureTarget) {
57         final int texBindQName;
58         switch(textureTarget) {
59             case GL.GL_TEXTURE_2D: texBindQName = GL.GL_TEXTURE_BINDING_2D; break;
60             case GL.GL_TEXTURE_CUBE_MAP: texBindQName = GL.GL_TEXTURE_BINDING_CUBE_MAP; break;
61             case GL2ES2.GL_TEXTURE_3D: texBindQName = GL2ES2.GL_TEXTURE_BINDING_3D; break;
62             case GL2GL3.GL_TEXTURE_1D: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D; break;
63             case GL2GL3.GL_TEXTURE_1D_ARRAY: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D_ARRAY; break;
64             case GL2ES3.GL_TEXTURE_2D_ARRAY: texBindQName = GL2ES3.GL_TEXTURE_BINDING_2D_ARRAY; break;
65             case GL2GL3.GL_TEXTURE_RECTANGLE: texBindQName = GL2GL3.GL_TEXTURE_BINDING_RECTANGLE; break;
66             case GL2GL3.GL_TEXTURE_BUFFER: texBindQName = GL2GL3.GL_TEXTURE_BINDING_BUFFER; break;
67             case GL2ES2.GL_TEXTURE_2D_MULTISAMPLE: texBindQName = GL2ES2.GL_TEXTURE_BINDING_2D_MULTISAMPLE; break;
68             case GL2ES2.GL_TEXTURE_2D_MULTISAMPLE_ARRAY: texBindQName = GL2ES2.GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; break;
69             default: texBindQName = 0;
70         }
71         return texBindQName;
72     }
73 
74     private final int target;
75     /**
76      * <pre>
77      *   0 - unit
78      *   1 - texture object
79      *   2 - GL.GL_TEXTURE_MAG_FILTER
80      *   3 - GL.GL_TEXTURE_MIN_FILTER
81      *   4 - GL.GL_TEXTURE_WRAP_S
82      *   5 - GL.GL_TEXTURE_WRAP_T
83      * </pre>
84      */
85     private final int[] state = new int[] { 0, 0, 0, 0, 0, 0 };
86 
toHexString(final int i)87     private static final String toHexString(final int i) { return "0x"+Integer.toHexString(i); }
88 
activeTexture(final GL gl)89     private static final int activeTexture(final GL gl) {
90         final int[] vi = { 0 };
91         gl.glGetIntegerv(GL.GL_ACTIVE_TEXTURE, vi, 0);
92         return vi[0];
93     }
94 
95     /**
96      * Creates a texture state for the retrieved active texture-unit and the given texture-target.
97      * See {@link TextureState}.
98      * @param gl current GL context's GL object
99      * @param textureTarget
100      * @throws GLException if textureTarget is not supported
101      */
TextureState(final GL gl, final int textureTarget)102     public TextureState(final GL gl, final int textureTarget) throws GLException {
103         this(gl, activeTexture(gl), textureTarget);
104     }
105 
106     /**
107      * Creates a texture state for the given active texture-unit and the given texture-target.
108      * See {@link TextureState}.
109      * @param gl current GL context's GL object
110      * @param textureUnit  of range [ {@link GL#GL_TEXTURE0}.. ]
111      * @param textureTarget
112      * @throws GLException if textureTarget is not supported
113      */
TextureState(final GL gl, final int textureUnit, final int textureTarget)114     public TextureState(final GL gl, final int textureUnit, final int textureTarget) throws GLException {
115         target = textureTarget;
116         state[0] = textureUnit;
117         final int texBindQName = getTextureTargetQueryName(textureTarget);
118         if( 0 == texBindQName ) {
119             throw new GLException("Unsupported textureTarget "+toHexString(textureTarget));
120         }
121         gl.glGetIntegerv(texBindQName, state, 1);
122         gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MAG_FILTER, state, 2);
123         gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MIN_FILTER, state, 3);
124         gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_S, state, 4);
125         gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_T, state, 5);
126     }
127 
128     /**
129      * Restores the texture-unit's texture-target state.
130      * <p>
131      * First the texture-unit is activated, then all states are restored.
132      * </p>
133      * @param gl current GL context's GL object
134      */
restore(final GL gl)135     public final void restore(final GL gl) {
136         gl.glActiveTexture(state[0]);
137         gl.glBindTexture(target, state[1]);
138         gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, state[2]);
139         gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, state[3]);
140         gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, state[4]);
141         gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, state[5]);
142     }
143 
144     /** Returns the texture-unit of this state, key value. Unit is of range [ {@link GL#GL_TEXTURE0}.. ]. */
getUnit()145     public final int getUnit() { return state[0]; }
146     /** Returns the texture-target of this state, key value. */
getTarget()147     public final int getTarget() { return target; }
148 
149     /** Returns the state's texture-object. */
getObject()150     public final int getObject() { return state[1]; }
151     /** Returns the state's mag-filter param. */
getMagFilter()152     public final int getMagFilter() { return state[2]; }
153     /** Returns the state's min-filter param. */
getMinFilter()154     public final int getMinFilter() { return state[3]; }
155     /** Returns the state's wrap-s param. */
getWrapS()156     public final int getWrapS() { return state[4]; }
157     /** Returns the state's wrap-t param. */
getWrapT()158     public final int getWrapT() { return state[5]; }
159 
160 
161     @Override
toString()162     public final String toString() {
163         return "TextureState[unit "+(state[0] - GL.GL_TEXTURE0)+", target "+toHexString(target)+
164                 ": obj "+toHexString(state[1])+
165                 ", filter[mag "+toHexString(state[2])+", min "+toHexString(state[3])+"], "+
166                 ": wrap[s "+toHexString(state[4])+", t "+toHexString(state[5])+"]]";
167     }
168 }
169