Home | History | Annotate | Download | only in mediafx
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.mediafx;
     18 
     19 import android.opengl.GLES20;
     20 
     21 import java.nio.ByteBuffer;
     22 import java.nio.ByteOrder;
     23 import java.nio.FloatBuffer;
     24 
     25 public class TextureRenderer {
     26 
     27     private int mProgram;
     28     private int mTexSamplerHandle;
     29     private int mTexCoordHandle;
     30     private int mPosCoordHandle;
     31 
     32     private FloatBuffer mTexVertices;
     33     private FloatBuffer mPosVertices;
     34 
     35     private int mViewWidth;
     36     private int mViewHeight;
     37 
     38     private int mTexWidth;
     39     private int mTexHeight;
     40 
     41     private static final String VERTEX_SHADER =
     42         "attribute vec4 a_position;\n" +
     43         "attribute vec2 a_texcoord;\n" +
     44         "varying vec2 v_texcoord;\n" +
     45         "void main() {\n" +
     46         "  gl_Position = a_position;\n" +
     47         "  v_texcoord = a_texcoord;\n" +
     48         "}\n";
     49 
     50     private static final String FRAGMENT_SHADER =
     51         "precision mediump float;\n" +
     52         "uniform sampler2D tex_sampler;\n" +
     53         "varying vec2 v_texcoord;\n" +
     54         "void main() {\n" +
     55         "  gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" +
     56         "}\n";
     57 
     58     private static final float[] TEX_VERTICES = {
     59         0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
     60     };
     61 
     62     private static final float[] POS_VERTICES = {
     63         -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f
     64     };
     65 
     66     private static final int FLOAT_SIZE_BYTES = 4;
     67 
     68     public void init() {
     69         // Create program
     70         mProgram = GLToolbox.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
     71 
     72         // Bind attributes and uniforms
     73         mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram,
     74                 "tex_sampler");
     75         mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texcoord");
     76         mPosCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_position");
     77 
     78         // Setup coordinate buffers
     79         mTexVertices = ByteBuffer.allocateDirect(
     80                 TEX_VERTICES.length * FLOAT_SIZE_BYTES)
     81                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
     82         mTexVertices.put(TEX_VERTICES).position(0);
     83         mPosVertices = ByteBuffer.allocateDirect(
     84                 POS_VERTICES.length * FLOAT_SIZE_BYTES)
     85                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
     86         mPosVertices.put(POS_VERTICES).position(0);
     87     }
     88 
     89     public void tearDown() {
     90         GLES20.glDeleteProgram(mProgram);
     91     }
     92 
     93     public void updateTextureSize(int texWidth, int texHeight) {
     94         mTexWidth = texWidth;
     95         mTexHeight = texHeight;
     96         computeOutputVertices();
     97     }
     98 
     99     public void updateViewSize(int viewWidth, int viewHeight) {
    100         mViewWidth = viewWidth;
    101         mViewHeight = viewHeight;
    102         computeOutputVertices();
    103     }
    104 
    105     public void renderTexture(int texId) {
    106         // Bind default FBO
    107         GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    108 
    109         // Use our shader program
    110         GLES20.glUseProgram(mProgram);
    111         GLToolbox.checkGlError("glUseProgram");
    112 
    113         // Set viewport
    114         GLES20.glViewport(0, 0, mViewWidth, mViewHeight);
    115         GLToolbox.checkGlError("glViewport");
    116 
    117         // Disable blending
    118         GLES20.glDisable(GLES20.GL_BLEND);
    119 
    120         // Set the vertex attributes
    121         GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false,
    122                 0, mTexVertices);
    123         GLES20.glEnableVertexAttribArray(mTexCoordHandle);
    124         GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT, false,
    125                 0, mPosVertices);
    126         GLES20.glEnableVertexAttribArray(mPosCoordHandle);
    127         GLToolbox.checkGlError("vertex attribute setup");
    128 
    129         // Set the input texture
    130         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    131         GLToolbox.checkGlError("glActiveTexture");
    132         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
    133         GLToolbox.checkGlError("glBindTexture");
    134         GLES20.glUniform1i(mTexSamplerHandle, 0);
    135 
    136         // Draw
    137         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    138         GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    139         GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    140     }
    141 
    142     private void computeOutputVertices() {
    143         if (mPosVertices != null) {
    144             float imgAspectRatio = mTexWidth / (float)mTexHeight;
    145             float viewAspectRatio = mViewWidth / (float)mViewHeight;
    146             float relativeAspectRatio = viewAspectRatio / imgAspectRatio;
    147             float x0, y0, x1, y1;
    148             if (relativeAspectRatio > 1.0f) {
    149                 x0 = -1.0f / relativeAspectRatio;
    150                 y0 = -1.0f;
    151                 x1 = 1.0f / relativeAspectRatio;
    152                 y1 = 1.0f;
    153             } else {
    154                 x0 = -1.0f;
    155                 y0 = -relativeAspectRatio;
    156                 x1 = 1.0f;
    157                 y1 = relativeAspectRatio;
    158             }
    159             float[] coords = new float[] { x0, y0, x1, y0, x0, y1, x1, y1 };
    160             mPosVertices.put(coords).position(0);
    161         }
    162     }
    163 }
    164