private boolean captureScreenshotTextureAndSetViewport() {
    if (!attachEglContext()) {
      return false;
    }
    try {
      if (!mTexNamesGenerated) {
        GLES10.glGenTextures(1, mTexNames, 0);
        if (checkGlErrors("glGenTextures")) {
          return false;
        }
        mTexNamesGenerated = true;
      }

      final SurfaceTexture st = new SurfaceTexture(mTexNames[0]);
      final Surface s = new Surface(st);
      try {
        SurfaceControl.screenshot(
            SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), s);
      } finally {
        s.release();
      }

      st.updateTexImage();
      st.getTransformMatrix(mTexMatrix);

      // Set up texture coordinates for a quad.
      // We might need to change this if the texture ends up being
      // a different size from the display for some reason.
      mTexCoordBuffer.put(0, 0f);
      mTexCoordBuffer.put(1, 0f);
      mTexCoordBuffer.put(2, 0f);
      mTexCoordBuffer.put(3, 1f);
      mTexCoordBuffer.put(4, 1f);
      mTexCoordBuffer.put(5, 1f);
      mTexCoordBuffer.put(6, 1f);
      mTexCoordBuffer.put(7, 0f);

      // Set up our viewport.
      GLES10.glViewport(0, 0, mDisplayWidth, mDisplayHeight);
      GLES10.glMatrixMode(GLES10.GL_PROJECTION);
      GLES10.glLoadIdentity();
      GLES10.glOrthof(0, mDisplayWidth, 0, mDisplayHeight, 0, 1);
      GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
      GLES10.glLoadIdentity();
      GLES10.glMatrixMode(GLES10.GL_TEXTURE);
      GLES10.glLoadIdentity();
      GLES10.glLoadMatrixf(mTexMatrix, 0);
    } finally {
      detachEglContext();
    }
    return true;
  }
  /**
   * 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);
  }
  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    /*
     * By default, OpenGL enables features that improve quality
     * but reduce performance. One might want to tweak that
     * especially on software renderer.
     */
    glDisable(GL_DITHER);

    /*
     * Some one-time OpenGL initialization can be made here
     * probably based on features of this particular context
     */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

    glClearColor(.5f, .5f, .5f, 1);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);

    /*
     * Create our texture. This has to be done each time the
     * surface is created.
     */

    int[] textures = new int[1];
    glGenTextures(1, textures, 0);

    mTextureID = textures[0];
    glBindTexture(GL_TEXTURE_2D, mTextureID);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    mTextureLoader.load(gl);
  }