content: /*
   * Copyright (C) 2014 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.example.android.mediaeffects;
  
  import android.opengl.GLES20;
  
  import java.nio.ByteBuffer;
  import java.nio.ByteOrder;
  import java.nio.FloatBuffer;
  
  public class TextureRenderer {
  
      private int mProgram;
      private int mTexSamplerHandle;
      private int mTexCoordHandle;
      private int mPosCoordHandle;
  
      private FloatBuffer mTexVertices;
      private FloatBuffer mPosVertices;
  
      private int mViewWidth;
      private int mViewHeight;
  
      private int mTexWidth;
      private int mTexHeight;
  
      private static final String VERTEX_SHADER =
          "attribute vec4 a_position;\n" +
          "attribute vec2 a_texcoord;\n" +
          "varying vec2 v_texcoord;\n" +
          "void main() {\n" +
          "  gl_Position = a_position;\n" +
          "  v_texcoord = a_texcoord;\n" +
          "}\n";
  
      private static final String FRAGMENT_SHADER =
          "precision mediump float;\n" +
          "uniform sampler2D tex_sampler;\n" +
          "varying vec2 v_texcoord;\n" +
          "void main() {\n" +
          "  gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" +
          "}\n";
  
      private static final float[] TEX_VERTICES = {
          0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
      };
  
      private static final float[] POS_VERTICES = {
          -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f
      };
  
      private static final int FLOAT_SIZE_BYTES = 4;
  
      public void init() {
          // Create program
          mProgram = GLToolbox.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
  
          // Bind attributes and uniforms
          mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram,
                  "tex_sampler");
          mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texcoord");
          mPosCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_position");
  
          // Setup coordinate buffers
          mTexVertices = ByteBuffer.allocateDirect(
                  TEX_VERTICES.length * FLOAT_SIZE_BYTES)
                  .order(ByteOrder.nativeOrder()).asFloatBuffer();
          mTexVertices.put(TEX_VERTICES).position(0);
          mPosVertices = ByteBuffer.allocateDirect(
                  POS_VERTICES.length * FLOAT_SIZE_BYTES)
                  .order(ByteOrder.nativeOrder()).asFloatBuffer();
          mPosVertices.put(POS_VERTICES).position(0);
      }
  
      public void tearDown() {
          GLES20.glDeleteProgram(mProgram);
      }
  
      public void updateTextureSize(int texWidth, int texHeight) {
          mTexWidth = texWidth;
          mTexHeight = texHeight;
          computeOutputVertices();
      }
  
      public void updateViewSize(int viewWidth, int viewHeight) {
          mViewWidth = viewWidth;
          mViewHeight = viewHeight;
          computeOutputVertices();
      }
  
      public void renderTexture(int texId) {
          // Bind default FBO
          GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
  
          // Use our shader program
          GLES20.glUseProgram(mProgram);
          GLToolbox.checkGlError("glUseProgram");
  
          // Set viewport
          GLES20.glViewport(0, 0, mViewWidth, mViewHeight);
          GLToolbox.checkGlError("glViewport");
  
          // Disable blending
          GLES20.glDisable(GLES20.GL_BLEND);
  
          // Set the vertex attributes
          GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false,
                  0, mTexVertices);
          GLES20.glEnableVertexAttribArray(mTexCoordHandle);
          GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT, false,
                  0, mPosVertices);
          GLES20.glEnableVertexAttribArray(mPosCoordHandle);
          GLToolbox.checkGlError("vertex attribute setup");
  
          // Set the input texture
          GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
          GLToolbox.checkGlError("glActiveTexture");
          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
          GLToolbox.checkGlError("glBindTexture");
          GLES20.glUniform1i(mTexSamplerHandle, 0);
  
          // Draw
          GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
          GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
          GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
      }
  
      private void computeOutputVertices() {
          if (mPosVertices != null) {
              float imgAspectRatio = mTexWidth / (float)mTexHeight;
              float viewAspectRatio = mViewWidth / (float)mViewHeight;
              float relativeAspectRatio = viewAspectRatio / imgAspectRatio;
              float x0, y0, x1, y1;
              if (relativeAspectRatio > 1.0f) {
                  x0 = -1.0f / relativeAspectRatio;
                  y0 = -1.0f;
                  x1 = 1.0f / relativeAspectRatio;
                  y1 = 1.0f;
              } else {
                  x0 = -1.0f;
                  y0 = -relativeAspectRatio;
                  x1 = 1.0f;
                  y1 = relativeAspectRatio;
              }
              float[] coords = new float[] { x0, y0, x1, y0, x0, y1, x1, y1 };
              mPosVertices.put(coords).position(0);
          }
      }
  
  }
  