| /* | |
| * Copyright (C) 2012 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.mediafx; | |
| 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); | |
| } | |
| } | |
| } |