1 /** 2 * Copyright 2010 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 29 package com.jogamp.opengl.util; 30 31 import com.jogamp.opengl.GL; 32 import com.jogamp.opengl.GL2; 33 import com.jogamp.opengl.GL2ES2; 34 import com.jogamp.opengl.GL2ES3; 35 import com.jogamp.opengl.GL2GL3; 36 import com.jogamp.opengl.GLContext; 37 import com.jogamp.opengl.GLException; 38 39 /** 40 * Utility to safely set and restore the PACK and UNPACK pixel storage mode, 41 * regardless of the GLProfile. 42 * <p> 43 * PACK for GPU to CPU transfers, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) ReadPixels}, etc. 44 * </p> 45 * <p> 46 * UNPACK for CPU o GPU transfers, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long) TexImage2D}, etc 47 * </p> 48 */ 49 public class GLPixelStorageModes { 50 private final int[] cachePack = new int[8]; 51 private final int[] cacheUnpack = new int[8]; 52 private boolean savedPack = false; 53 private boolean savedUnpack = false; 54 55 /** Create instance w/o {@link #saveAll(GL)} */ GLPixelStorageModes()56 public GLPixelStorageModes() {} 57 58 /** Create instance w/ {@link #saveAll(GL)} */ GLPixelStorageModes(final GL gl)59 public GLPixelStorageModes(final GL gl) { saveAll(gl); } 60 61 /** 62 * Sets the {@link GL#GL_PACK_ALIGNMENT}. 63 * <p> 64 * Saves the PACK pixel storage modes and {@link #resetPack(GL) resets} them if not saved yet, see {@link #savePack(GL)}. 65 * </p> 66 */ setPackAlignment(final GL gl, final int packAlignment)67 public final void setPackAlignment(final GL gl, final int packAlignment) { 68 savePack(gl); 69 gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, packAlignment); 70 } 71 72 /** 73 * Sets the {@link GL#GL_UNPACK_ALIGNMENT}. 74 * <p> 75 * Saves the UNPACK pixel storage modes and {@link #resetUnpack(GL) resets} them if not saved yet, see {@link #saveUnpack(GL)}. 76 * </p> 77 */ setUnpackAlignment(final GL gl, final int unpackAlignment)78 public final void setUnpackAlignment(final GL gl, final int unpackAlignment) { 79 saveUnpack(gl); 80 gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, unpackAlignment); 81 } 82 83 /** 84 * Sets the {@link GL#GL_PACK_ALIGNMENT} and {@link GL#GL_UNPACK_ALIGNMENT}. 85 * <p> 86 * Saves the PACK and UNPACK pixel storage modes and resets them if not saved yet, see {@link #saveAll(GL)}. 87 * </p> 88 */ setAlignment(final GL gl, final int packAlignment, final int unpackAlignment)89 public final void setAlignment(final GL gl, final int packAlignment, final int unpackAlignment) { 90 setPackAlignment(gl, packAlignment); 91 setUnpackAlignment(gl, unpackAlignment); 92 } 93 94 /** 95 * Sets the {@link GL2ES3#GL_PACK_ROW_LENGTH}. 96 * <p> 97 * Saves the PACK pixel storage modes and {@link #resetPack(GL) resets} them if not saved yet, see {@link #savePack(GL)}. 98 * </p> 99 */ setPackRowLength(final GL2ES3 gl, final int packRowLength)100 public final void setPackRowLength(final GL2ES3 gl, final int packRowLength) { 101 savePack(gl); 102 gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, packRowLength); 103 } 104 105 /** 106 * Sets the {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. 107 * <p> 108 * Saves the UNPACK pixel storage modes and {@link #resetUnpack(GL) resets} them if not saved yet, see {@link #saveUnpack(GL)}. 109 * </p> 110 */ setUnpackRowLength(final GL2ES3 gl, final int unpackRowLength)111 public final void setUnpackRowLength(final GL2ES3 gl, final int unpackRowLength) { 112 saveUnpack(gl); 113 gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, unpackRowLength); 114 } 115 116 /** 117 * Sets the {@link GL2ES3#GL_PACK_ROW_LENGTH} and {@link GL2ES2#GL_UNPACK_ROW_LENGTH} if {@link GL#isGL2ES3()}. 118 * <p> 119 * Saves the PACK and UNPACK pixel storage modes and resets them if not saved yet, see {@link #saveAll(GL)}. 120 * </p> 121 */ setRowLength(final GL2ES3 gl, final int packRowLength, final int unpackRowLength)122 public final void setRowLength(final GL2ES3 gl, final int packRowLength, final int unpackRowLength) { 123 setPackRowLength(gl, packRowLength); 124 setUnpackRowLength(gl, unpackRowLength); 125 } 126 127 /** 128 * Saves PACK and UNPACK pixel storage modes and {@link #resetAll(GL) resets} them, 129 * i.e. issues {@link #savePack(GL)} and {@link #saveUnpack(GL)}. 130 * <p> 131 * Operation is skipped, if the modes were already saved. 132 * </p> 133 * <p> 134 * Restore via {@link #restore(GL)} 135 * </p> 136 */ saveAll(final GL gl)137 public final void saveAll(final GL gl) { 138 savePack(gl); 139 saveUnpack(gl); 140 } 141 142 /** 143 * Resets PACK and UNPACK pixel storage modes to their default value, 144 * i.e. issues {@link #resetPack(GL)} and {@link #resetUnpack(GL)}. 145 */ resetAll(final GL gl)146 public final void resetAll(final GL gl) { 147 resetPack(gl); 148 resetUnpack(gl); 149 } 150 151 /** 152 * Restores PACK and UNPACK pixel storage mode previously saved w/ {@link #saveAll(GL)} 153 * or {@link #savePack(GL)} and {@link #saveUnpack(GL)}. 154 * @throws GLException if neither PACK nor UNPACK modes were saved. 155 */ restore(final GL gl)156 public final void restore(final GL gl) throws GLException { 157 if(!savedPack && !savedUnpack) { 158 throw new GLException("Neither PACK nor UNPACK pixel storage modes were saved"); 159 } 160 if( savedPack ) { 161 restorePack(gl); 162 savedPack = false; 163 } 164 if( savedUnpack ) { 165 restoreUnpack(gl); 166 savedUnpack = false; 167 } 168 } 169 170 /** 171 * Resets PACK pixel storage modes to their default value. 172 */ resetPack(final GL gl)173 public final void resetPack(final GL gl) { 174 // Compared w/ ES2, ES3 and GL3-core spec 175 gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 4); // es2, es3, gl3 176 if( gl.isGL2ES3() ) { 177 gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, 0); // es3, gl3 178 gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, 0); // es3, gl3 179 gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, 0); // es3, gl3 180 if( gl.isGL2GL3() ) { 181 gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, GL.GL_FALSE); // gl3 182 gl.glPixelStorei(GL2GL3.GL_PACK_LSB_FIRST, GL.GL_FALSE); // gl3 183 if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_2) >= 0 ) { 184 gl.glPixelStorei(GL2GL3.GL_PACK_IMAGE_HEIGHT, 0); // gl3, GL_VERSION_1_2 185 gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_IMAGES, 0); // gl3, GL_VERSION_1_2 186 } 187 } 188 } 189 } 190 /** 191 * Saves PACK pixel storage modes and {@link #resetPack(GL) resets} them. 192 * <p> 193 * Operation is skipped, if the modes were already saved. 194 * </p> 195 * <p> 196 * Restore via {@link #restore(GL)} 197 * </p> 198 */ savePack(final GL gl)199 public final void savePack(final GL gl) { 200 if(savedPack) { 201 return; 202 } 203 if( gl.isGL2() ) { 204 // See GLStateTracker.pushAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT) 205 gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT); 206 } else { 207 // ES1 or ES2 deals with pack/unpack alignment only 208 gl.glGetIntegerv(GL.GL_PACK_ALIGNMENT, cachePack, 0); 209 if( gl.isGL2ES3() ) { 210 gl.glGetIntegerv(GL2ES3.GL_PACK_ROW_LENGTH, cachePack, 1); 211 gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_ROWS, cachePack, 2); 212 gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_PIXELS, cachePack, 3); 213 if( gl.isGL2GL3() ) { 214 gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES, cachePack, 4); 215 gl.glGetIntegerv(GL2GL3.GL_PACK_LSB_FIRST, cachePack, 5); 216 gl.glGetIntegerv(GL2GL3.GL_PACK_IMAGE_HEIGHT, cachePack, 6); 217 gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_IMAGES, cachePack, 7); 218 } 219 } 220 } 221 savedPack = true; 222 resetPack(gl); 223 } restorePack(final GL gl)224 private final void restorePack(final GL gl) { 225 if( gl.isGL2() ) { 226 gl.getGL2().glPopClientAttrib(); 227 } else { 228 gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, cachePack[0]); 229 if( gl.isGL2ES3() ) { 230 gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, cachePack[1]); 231 gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, cachePack[2]); 232 gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, cachePack[3]); 233 if( gl.isGL2GL3() ) { 234 gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, cachePack[4]); 235 gl.glPixelStorei(GL2GL3.GL_PACK_LSB_FIRST, cachePack[5]); 236 gl.glPixelStorei(GL2GL3.GL_PACK_IMAGE_HEIGHT, cachePack[6]); 237 gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_IMAGES, cachePack[7]); 238 } 239 } 240 } 241 } 242 243 /** 244 * Resets UNPACK pixel storage modes to their default value. 245 */ resetUnpack(final GL gl)246 public final void resetUnpack(final GL gl) { 247 // Compared w/ ES2, ES3 and GL3-core spec 248 gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 4); // es2, es3, gl3 249 if( gl.isGL2ES3() ) { 250 gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, 0); // es3, gl3 251 gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, 0); // es3, gl3 252 gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0); // es3, gl3 253 if( gl.isGL2GL3() ) { 254 if( gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_2) >= 0 ) { 255 gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0); // es3, gl3, GL_VERSION_1_2 256 gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0); // es3, gl3, GL_VERSION_1_2 257 } 258 gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE); // gl3 259 gl.glPixelStorei(GL2GL3.GL_UNPACK_LSB_FIRST, GL.GL_FALSE); // gl3 260 } else { 261 gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0); // es3, gl3, GL_VERSION_1_2 262 gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, 0); // es3, gl3, GL_VERSION_1_2 263 } 264 } 265 } 266 /** 267 * Saves UNPACK pixel storage modes and {@link #resetUnpack(GL) resets} them. 268 * <p> 269 * Operation is skipped, if the modes were already saved. 270 * </p> 271 * <p> 272 * Restore via {@link #restore(GL)} 273 * </p> 274 */ saveUnpack(final GL gl)275 public final void saveUnpack(final GL gl) { 276 if(savedUnpack) { 277 return; 278 } 279 if( gl.isGL2() ) { 280 // See GLStateTracker.pushAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT) 281 gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT); 282 } else { 283 // ES1 or ES2 deals with pack/unpack alignment only 284 gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, cacheUnpack, 0); 285 if( gl.isGL2ES3() ) { 286 gl.glGetIntegerv(GL2ES2.GL_UNPACK_ROW_LENGTH, cacheUnpack, 1); 287 gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_ROWS, cacheUnpack, 2); 288 gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_PIXELS, cacheUnpack, 3); 289 gl.glGetIntegerv(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, cacheUnpack, 4); 290 gl.glGetIntegerv(GL2ES3.GL_UNPACK_SKIP_IMAGES, cacheUnpack, 5); 291 if( gl.isGL2GL3() ) { 292 gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES, cacheUnpack, 6); 293 gl.glGetIntegerv(GL2GL3.GL_UNPACK_LSB_FIRST, cacheUnpack, 7); 294 } 295 } 296 } 297 savedUnpack = true; 298 resetUnpack(gl); 299 } restoreUnpack(final GL gl)300 private final void restoreUnpack(final GL gl) { 301 if( gl.isGL2() ) { 302 gl.getGL2().glPopClientAttrib(); 303 } else { 304 gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, cacheUnpack[0]); 305 if( gl.isGL2ES3() ) { 306 gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, cacheUnpack[1]); 307 gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, cacheUnpack[2]); 308 gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, cacheUnpack[3]); 309 gl.glPixelStorei(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, cacheUnpack[4]); 310 gl.glPixelStorei(GL2ES3.GL_UNPACK_SKIP_IMAGES, cacheUnpack[5]); 311 if( gl.isGL2GL3() ) { 312 gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, cacheUnpack[6]); 313 gl.glPixelStorei(GL2GL3.GL_UNPACK_LSB_FIRST, cacheUnpack[7]); 314 } 315 } 316 } 317 } 318 } 319 320 321