/*
* Copyright (C) 2011 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.
*/
#include "SurfaceTextureRenderer.h"
#include <string.h>
#include <GLES2/gl2ext.h>
const GLfloat g_vVertices[] = {
-1.f, -1.f, 0.0f, 1.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
1.f, -1.f, 0.0f, 1.0f, // Position 1
1.0f, 0.0f, // TexCoord 1
-1.f, 1.f, 0.0f, 1.0f, // Position 2
0.0f, 1.0f, // TexCoord 2
1.f, 1.f, 0.0f, 1.0f, // Position 3
1.0f, 1.0f // TexCoord 3
};
GLushort g_iIndices2[] = { 0, 1, 2, 3 };
const int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65;
const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
SurfaceTextureRenderer::SurfaceTextureRenderer() : Renderer() {
memset(mSTMatrix, 0.0, 16*sizeof(float));
mSTMatrix[0] = 1.0f;
mSTMatrix[5] = 1.0f;
mSTMatrix[10] = 1.0f;
mSTMatrix[15] = 1.0f;
}
SurfaceTextureRenderer::~SurfaceTextureRenderer() {
}
void SurfaceTextureRenderer::SetViewportMatrix(int w, int h, int W, int H)
{
for(int i=0; i<16; i++)
{
mViewportMatrix[i] = 0.0f;
}
mViewportMatrix[0] = float(w)/float(W);
mViewportMatrix[5] = float(h)/float(H);
mViewportMatrix[10] = 1.0f;
mViewportMatrix[12] = -1.0f + float(w)/float(W);
mViewportMatrix[13] = -1.0f + float(h)/float(H);
mViewportMatrix[15] = 1.0f;
}
void SurfaceTextureRenderer::SetScalingMatrix(float xscale, float yscale)
{
for(int i=0; i<16; i++)
{
mScalingMatrix[i] = 0.0f;
}
mScalingMatrix[0] = xscale;
mScalingMatrix[5] = yscale;
mScalingMatrix[10] = 1.0f;
mScalingMatrix[15] = 1.0f;
}
void SurfaceTextureRenderer::SetSTMatrix(float *stmat)
{
memcpy(mSTMatrix, stmat, 16*sizeof(float));
}
bool SurfaceTextureRenderer::InitializeGLProgram()
{
bool succeeded = false;
do {
GLuint glProgram;
glProgram = createProgram(VertexShaderSource(),
FragmentShaderSource());
if (!glProgram) {
break;
}
glUseProgram(glProgram);
if (!checkGlError("glUseProgram")) break;
maPositionHandle = glGetAttribLocation(glProgram, "aPosition");
checkGlError("glGetAttribLocation aPosition");
maTextureHandle = glGetAttribLocation(glProgram, "aTextureCoord");
checkGlError("glGetAttribLocation aTextureCoord");
muSTMatrixHandle = glGetUniformLocation(glProgram, "uSTMatrix");
checkGlError("glGetUniformLocation uSTMatrix");
mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
mGlProgram = glProgram;
succeeded = true;
} while (false);
if (!succeeded && (mGlProgram != 0))
{
glDeleteProgram(mGlProgram);
checkGlError("glDeleteProgram");
mGlProgram = 0;
}
return succeeded;
}
bool SurfaceTextureRenderer::DrawTexture(GLfloat *affine)
{
bool succeeded = false;
do {
bool rt = (mFrameBuffer == NULL)?
SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
SetupGraphics(mFrameBuffer);
if(!rt)
break;
glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE0);
if (!checkGlError("glActiveTexture")) break;
const GLenum texture_type = InputTextureType();
glBindTexture(texture_type, mInputTextureName);
if (!checkGlError("glBindTexture")) break;
glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix);
glUniformMatrix4fv(muSTMatrixHandle, 1, GL_FALSE, mSTMatrix);
// Load the vertex position
glVertexAttribPointer(maPositionHandle, 4, GL_FLOAT,
GL_FALSE, VERTEX_STRIDE, g_vVertices);
glEnableVertexAttribArray(maPositionHandle);
// Load the texture coordinate
glVertexAttribPointer(maTextureHandle, 2, GL_FLOAT,
GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
glEnableVertexAttribArray(maTextureHandle);
// And, finally, execute the GL draw command.
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices2);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
succeeded = true;
} while (false);
return succeeded;
}
const char* SurfaceTextureRenderer::VertexShaderSource() const
{
static const char gVertexShader[] =
"uniform mat4 uSTMatrix;\n"
"uniform mat4 u_scalingtrans; \n"
"attribute vec4 aPosition;\n"
"attribute vec4 aTextureCoord;\n"
"varying vec2 vTextureNormCoord;\n"
"void main() {\n"
" gl_Position = u_scalingtrans * aPosition;\n"
" vTextureNormCoord = (uSTMatrix * aTextureCoord).xy;\n"
"}\n";
return gVertexShader;
}
const char* SurfaceTextureRenderer::FragmentShaderSource() const
{
static const char gFragmentShader[] =
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float;\n"
"varying vec2 vTextureNormCoord;\n"
"uniform samplerExternalOES sTexture;\n"
"void main() {\n"
" gl_FragColor = texture2D(sTexture, vTextureNormCoord);\n"
"}\n";
return gFragmentShader;
}