/**
   * Init CameraManager gl texture id, camera SurfaceTexture, bind to EXTERNAL_OES, and redirect
   * camera preview to the surfaceTexture.
   *
   * @throws IOException when camera cannot be open
   */
  private void initCameraSurface() throws IOException {

    // Gen openGL texture id
    int texture[] = new int[1];
    GLES10.glGenTextures(1, texture, 0);
    mCameraTextureId = texture[0];

    if (mCameraTextureId == 0) {
      throw new RuntimeException("Cannot create openGL texture (initCameraSurface())");
    }

    // Camera preview is redirected to SurfaceTexture.
    // SurfaceTexture works with TEXTURE_EXTERNAL_OES, so we bind this textureId so that camera
    // will automatically fill it with its video.
    GLES10.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mCameraTextureId);

    // Can't do mipmapping with camera source
    GLES10.glTexParameterf(
        GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES10.GL_TEXTURE_MIN_FILTER, GLES10.GL_LINEAR);
    GLES10.glTexParameterf(
        GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR);

    // Clamp to edge is the only option
    GLES10.glTexParameterf(
        GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES10.GL_TEXTURE_WRAP_S, GLES10.GL_CLAMP_TO_EDGE);
    GLES10.glTexParameterf(
        GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES10.GL_TEXTURE_WRAP_T, GLES10.GL_CLAMP_TO_EDGE);

    // create a SurfaceTexture associated to this openGL texture...
    mCameraSurfaceTex = new SurfaceTexture(mCameraTextureId);
    mCameraSurfaceTex.setDefaultBufferSize(640, 480);

    // ... and redirect camera preview to it
    mCameraManager.setPreviewSurface(mCameraSurfaceTex);

    // Setup viewfinder
    mViewFinder = new TexturedPlane(mViewFinderSize);
    mViewFinder.setTexture(
        BitmapDecoder.safeDecodeBitmap(mContext.getResources(), VIEWFINDER_RESSOURCE_ID));
    mViewFinder.recycleTexture();
    mViewFinder.translate(0, 0, VIEWFINDER_DISTANCE);
    mViewFinder.setAlpha(VIEWFINDER_ATTENUATION_ALPHA);
  }