private ProgramHolder createProgramHolder(final boolean aberrationCorrected) {
   ProgramHolder holder;
   GLStateBackup state;
   if (aberrationCorrected) {
     holder = new ProgramHolderAberration();
     holder.program = this.createProgram(VERTEX_SHADER_ABERRATION, FRAGMENT_SHADER_ABERRATION);
     if (holder.program == 0) {
       throw new RuntimeException("Could not create aberration-corrected program");
     }
     state = this.mGLStateBackupAberration;
   } else {
     holder = new ProgramHolder();
     holder.program = this.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
     if (holder.program == 0) {
       throw new RuntimeException("Could not create program");
     }
     state = this.mGLStateBackup;
   }
   holder.aPosition = GLES20.glGetAttribLocation(holder.program, "aPosition");
   this.checkGlError("glGetAttribLocation aPosition");
   if (holder.aPosition == -1) {
     throw new RuntimeException("Could not get attrib location for aPosition");
   }
   state.addTrackedVertexAttribute(holder.aPosition);
   holder.aVignette = GLES20.glGetAttribLocation(holder.program, "aVignette");
   this.checkGlError("glGetAttribLocation aVignette");
   if (holder.aVignette == -1) {
     throw new RuntimeException("Could not get attrib location for aVignette");
   }
   state.addTrackedVertexAttribute(holder.aVignette);
   if (aberrationCorrected) {
     ((ProgramHolderAberration) holder).aRedTextureCoord =
         GLES20.glGetAttribLocation(holder.program, "aRedTextureCoord");
     this.checkGlError("glGetAttribLocation aRedTextureCoord");
     if (((ProgramHolderAberration) holder).aRedTextureCoord == -1) {
       throw new RuntimeException("Could not get attrib location for aRedTextureCoord");
     }
     ((ProgramHolderAberration) holder).aGreenTextureCoord =
         GLES20.glGetAttribLocation(holder.program, "aGreenTextureCoord");
     this.checkGlError("glGetAttribLocation aGreenTextureCoord");
     if (((ProgramHolderAberration) holder).aGreenTextureCoord == -1) {
       throw new RuntimeException("Could not get attrib location for aGreenTextureCoord");
     }
     state.addTrackedVertexAttribute(((ProgramHolderAberration) holder).aRedTextureCoord);
     state.addTrackedVertexAttribute(((ProgramHolderAberration) holder).aGreenTextureCoord);
   }
   holder.aBlueTextureCoord = GLES20.glGetAttribLocation(holder.program, "aBlueTextureCoord");
   this.checkGlError("glGetAttribLocation aBlueTextureCoord");
   if (holder.aBlueTextureCoord == -1) {
     throw new RuntimeException("Could not get attrib location for aBlueTextureCoord");
   }
   state.addTrackedVertexAttribute(holder.aBlueTextureCoord);
   holder.uTextureCoordScale = GLES20.glGetUniformLocation(holder.program, "uTextureCoordScale");
   this.checkGlError("glGetUniformLocation uTextureCoordScale");
   if (holder.uTextureCoordScale == -1) {
     throw new RuntimeException("Could not get attrib location for uTextureCoordScale");
   }
   holder.uTextureSampler = GLES20.glGetUniformLocation(holder.program, "uTextureSampler");
   this.checkGlError("glGetUniformLocation uTextureSampler");
   if (holder.uTextureSampler == -1) {
     throw new RuntimeException("Could not get attrib location for uTextureSampler");
   }
   return holder;
 }