1441e847feb0e055ecb004802802cea07782ab228Andy McFadden/*
2441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Copyright 2013 The Android Open Source Project
3441e847feb0e055ecb004802802cea07782ab228Andy McFadden *
4441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License");
5441e847feb0e055ecb004802802cea07782ab228Andy McFadden * you may not use this file except in compliance with the License.
6441e847feb0e055ecb004802802cea07782ab228Andy McFadden * You may obtain a copy of the License at
7441e847feb0e055ecb004802802cea07782ab228Andy McFadden *
8441e847feb0e055ecb004802802cea07782ab228Andy McFadden *      http://www.apache.org/licenses/LICENSE-2.0
9441e847feb0e055ecb004802802cea07782ab228Andy McFadden *
10441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Unless required by applicable law or agreed to in writing, software
11441e847feb0e055ecb004802802cea07782ab228Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS,
12441e847feb0e055ecb004802802cea07782ab228Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13441e847feb0e055ecb004802802cea07782ab228Andy McFadden * See the License for the specific language governing permissions and
14441e847feb0e055ecb004802802cea07782ab228Andy McFadden * limitations under the License.
15441e847feb0e055ecb004802802cea07782ab228Andy McFadden */
16441e847feb0e055ecb004802802cea07782ab228Andy McFadden
17441e847feb0e055ecb004802802cea07782ab228Andy McFadden#define LOG_TAG "ScreenRecord"
18441e847feb0e055ecb004802802cea07782ab228Andy McFadden//#define LOG_NDEBUG 0
19441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <utils/Log.h>
20441e847feb0e055ecb004802802cea07782ab228Andy McFadden
21441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include "Program.h"
22441e847feb0e055ecb004802802cea07782ab228Andy McFadden
23441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <GLES2/gl2.h>
24441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <GLES2/gl2ext.h>
25441e847feb0e055ecb004802802cea07782ab228Andy McFadden
26441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <assert.h>
27441e847feb0e055ecb004802802cea07782ab228Andy McFadden
28441e847feb0e055ecb004802802cea07782ab228Andy McFaddenusing namespace android;
29441e847feb0e055ecb004802802cea07782ab228Andy McFadden
30441e847feb0e055ecb004802802cea07782ab228Andy McFadden// 4x4 identity matrix
31441e847feb0e055ecb004802802cea07782ab228Andy McFaddenconst float Program::kIdentity[] = {
32441e847feb0e055ecb004802802cea07782ab228Andy McFadden        1.0f, 0.0f, 0.0f, 0.0f,
33441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f, 1.0f, 0.0f, 0.0f,
34441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f, 0.0f, 1.0f, 0.0f,
35441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f, 0.0f, 0.0f, 1.0f
36441e847feb0e055ecb004802802cea07782ab228Andy McFadden};
37441e847feb0e055ecb004802802cea07782ab228Andy McFadden
38441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Simple vertex shader.  Texture coord calc includes matrix for GLConsumer
39441e847feb0e055ecb004802802cea07782ab228Andy McFadden// transform.
40441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatic const char* kVertexShader =
41441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "uniform mat4 uMVPMatrix;\n"
42441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "uniform mat4 uGLCMatrix;\n"
43441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "attribute vec4 aPosition;\n"
44441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "attribute vec4 aTextureCoord;\n"
45441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "varying vec2 vTextureCoord;\n"
46441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "void main() {\n"
47441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "    gl_Position = uMVPMatrix * aPosition;\n"
48441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "    vTextureCoord = (uGLCMatrix * aTextureCoord).xy;\n"
49441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "}\n";
50441e847feb0e055ecb004802802cea07782ab228Andy McFadden
51441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Trivial fragment shader for external texture.
52441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatic const char* kExtFragmentShader =
53441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "#extension GL_OES_EGL_image_external : require\n"
54441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "precision mediump float;\n"
55441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "varying vec2 vTextureCoord;\n"
56441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "uniform samplerExternalOES uTexture;\n"
57441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "void main() {\n"
58441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "    gl_FragColor = texture2D(uTexture, vTextureCoord);\n"
59441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "}\n";
60441e847feb0e055ecb004802802cea07782ab228Andy McFadden
61441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Trivial fragment shader for mundane texture.
62441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatic const char* kFragmentShader =
63441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "precision mediump float;\n"
64441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "varying vec2 vTextureCoord;\n"
65441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "uniform sampler2D uTexture;\n"
66441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "void main() {\n"
67441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "    gl_FragColor = texture2D(uTexture, vTextureCoord);\n"
68441e847feb0e055ecb004802802cea07782ab228Andy McFadden        //"    gl_FragColor = vec4(0.2, 1.0, 0.2, 1.0);\n"
69441e847feb0e055ecb004802802cea07782ab228Andy McFadden        "}\n";
70441e847feb0e055ecb004802802cea07782ab228Andy McFadden
71441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::setup(ProgramType type) {
72441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("Program::setup type=%d", type);
73441e847feb0e055ecb004802802cea07782ab228Andy McFadden    status_t err;
74441e847feb0e055ecb004802802cea07782ab228Andy McFadden
75441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mProgramType = type;
76441e847feb0e055ecb004802802cea07782ab228Andy McFadden
77441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLuint program;
78441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (type == PROGRAM_TEXTURE_2D) {
79441e847feb0e055ecb004802802cea07782ab228Andy McFadden        err = createProgram(&program, kVertexShader, kFragmentShader);
80441e847feb0e055ecb004802802cea07782ab228Andy McFadden    } else {
81441e847feb0e055ecb004802802cea07782ab228Andy McFadden        err = createProgram(&program, kVertexShader, kExtFragmentShader);
82441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
83441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err != NO_ERROR) {
84441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return err;
85441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
86441e847feb0e055ecb004802802cea07782ab228Andy McFadden    assert(program != 0);
87441e847feb0e055ecb004802802cea07782ab228Andy McFadden
88441e847feb0e055ecb004802802cea07782ab228Andy McFadden    maPositionLoc = glGetAttribLocation(program, "aPosition");
89441e847feb0e055ecb004802802cea07782ab228Andy McFadden    maTextureCoordLoc = glGetAttribLocation(program, "aTextureCoord");
90441e847feb0e055ecb004802802cea07782ab228Andy McFadden    muMVPMatrixLoc = glGetUniformLocation(program, "uMVPMatrix");
91441e847feb0e055ecb004802802cea07782ab228Andy McFadden    muGLCMatrixLoc = glGetUniformLocation(program, "uGLCMatrix");
92441e847feb0e055ecb004802802cea07782ab228Andy McFadden    muTextureLoc = glGetUniformLocation(program, "uTexture");
93441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if ((maPositionLoc | maTextureCoordLoc | muMVPMatrixLoc |
94441e847feb0e055ecb004802802cea07782ab228Andy McFadden            muGLCMatrixLoc | muTextureLoc) == -1) {
95441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("Attrib/uniform lookup failed: %#x", glGetError());
96441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDeleteProgram(program);
97441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
98441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
99441e847feb0e055ecb004802802cea07782ab228Andy McFadden
100441e847feb0e055ecb004802802cea07782ab228Andy McFadden    mProgram = program;
101441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
102441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
103441e847feb0e055ecb004802802cea07782ab228Andy McFadden
104441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid Program::release() {
105441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("Program::release");
106441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (mProgram != 0) {
107441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDeleteProgram(mProgram);
108441e847feb0e055ecb004802802cea07782ab228Andy McFadden        mProgram = 0;
109441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
110441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
111441e847feb0e055ecb004802802cea07782ab228Andy McFadden
112441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::createProgram(GLuint* outPgm, const char* vertexShader,
113441e847feb0e055ecb004802802cea07782ab228Andy McFadden        const char* fragmentShader) {
114441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLuint vs, fs;
115441e847feb0e055ecb004802802cea07782ab228Andy McFadden    status_t err;
116441e847feb0e055ecb004802802cea07782ab228Andy McFadden
117441e847feb0e055ecb004802802cea07782ab228Andy McFadden    err = compileShader(GL_VERTEX_SHADER, vertexShader, &vs);
118441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err != NO_ERROR) {
119441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return err;
120441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
121441e847feb0e055ecb004802802cea07782ab228Andy McFadden    err = compileShader(GL_FRAGMENT_SHADER, fragmentShader, &fs);
122441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err != NO_ERROR) {
123441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDeleteShader(vs);
124441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return err;
125441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
126441e847feb0e055ecb004802802cea07782ab228Andy McFadden
127441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLuint program;
128441e847feb0e055ecb004802802cea07782ab228Andy McFadden    err = linkShaderProgram(vs, fs, &program);
129441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glDeleteShader(vs);
130441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glDeleteShader(fs);
131441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err == NO_ERROR) {
132441e847feb0e055ecb004802802cea07782ab228Andy McFadden        *outPgm = program;
133441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
134441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return err;
135441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
136441e847feb0e055ecb004802802cea07782ab228Andy McFadden
137441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::compileShader(GLenum shaderType, const char* src,
138441e847feb0e055ecb004802802cea07782ab228Andy McFadden        GLuint* outShader) {
139441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLuint shader = glCreateShader(shaderType);
140441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (shader == 0) {
141441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("glCreateShader error: %#x", glGetError());
142441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
143441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
144441e847feb0e055ecb004802802cea07782ab228Andy McFadden
145441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glShaderSource(shader, 1, &src, NULL);
146441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glCompileShader(shader);
147441e847feb0e055ecb004802802cea07782ab228Andy McFadden
148441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLint compiled = 0;
149441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
150441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (!compiled) {
151441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("Compile of shader type %d failed", shaderType);
152441e847feb0e055ecb004802802cea07782ab228Andy McFadden        GLint infoLen = 0;
153441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
154441e847feb0e055ecb004802802cea07782ab228Andy McFadden        if (infoLen) {
155441e847feb0e055ecb004802802cea07782ab228Andy McFadden            char* buf = new char[infoLen];
156441e847feb0e055ecb004802802cea07782ab228Andy McFadden            if (buf) {
157441e847feb0e055ecb004802802cea07782ab228Andy McFadden                glGetShaderInfoLog(shader, infoLen, NULL, buf);
158441e847feb0e055ecb004802802cea07782ab228Andy McFadden                ALOGE("Compile log: %s", buf);
159441e847feb0e055ecb004802802cea07782ab228Andy McFadden                delete[] buf;
160441e847feb0e055ecb004802802cea07782ab228Andy McFadden            }
161441e847feb0e055ecb004802802cea07782ab228Andy McFadden        }
162441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDeleteShader(shader);
163441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
164441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
165441e847feb0e055ecb004802802cea07782ab228Andy McFadden    *outShader = shader;
166441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
167441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
168441e847feb0e055ecb004802802cea07782ab228Andy McFadden
169441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::linkShaderProgram(GLuint vs, GLuint fs, GLuint* outPgm) {
170441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLuint program = glCreateProgram();
171441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (program == 0) {
172441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("glCreateProgram error: %#x", glGetError());
173441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
174441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
175441e847feb0e055ecb004802802cea07782ab228Andy McFadden
176441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glAttachShader(program, vs);
177441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glAttachShader(program, fs);
178441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glLinkProgram(program);
179441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLint linkStatus = GL_FALSE;
180441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
181441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (linkStatus != GL_TRUE) {
182441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("glLinkProgram failed");
183441e847feb0e055ecb004802802cea07782ab228Andy McFadden        GLint bufLength = 0;
184441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
185441e847feb0e055ecb004802802cea07782ab228Andy McFadden        if (bufLength) {
186441e847feb0e055ecb004802802cea07782ab228Andy McFadden            char* buf = new char[bufLength];
187441e847feb0e055ecb004802802cea07782ab228Andy McFadden            if (buf) {
188441e847feb0e055ecb004802802cea07782ab228Andy McFadden                glGetProgramInfoLog(program, bufLength, NULL, buf);
189441e847feb0e055ecb004802802cea07782ab228Andy McFadden                ALOGE("Link log: %s", buf);
190441e847feb0e055ecb004802802cea07782ab228Andy McFadden                delete[] buf;
191441e847feb0e055ecb004802802cea07782ab228Andy McFadden            }
192441e847feb0e055ecb004802802cea07782ab228Andy McFadden        }
193441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDeleteProgram(program);
194441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
195441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
196441e847feb0e055ecb004802802cea07782ab228Andy McFadden
197441e847feb0e055ecb004802802cea07782ab228Andy McFadden    *outPgm = program;
198441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
199441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
200441e847feb0e055ecb004802802cea07782ab228Andy McFadden
201441e847feb0e055ecb004802802cea07782ab228Andy McFadden
202441e847feb0e055ecb004802802cea07782ab228Andy McFadden
203441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::blit(GLuint texName, const float* texMatrix,
204587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        int32_t x, int32_t y, int32_t w, int32_t h, bool invert) const {
205441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("Program::blit %d xy=%d,%d wh=%d,%d", texName, x, y, w, h);
206441e847feb0e055ecb004802802cea07782ab228Andy McFadden
207441e847feb0e055ecb004802802cea07782ab228Andy McFadden    const float pos[] = {
208441e847feb0e055ecb004802802cea07782ab228Andy McFadden        float(x),   float(y+h),
209441e847feb0e055ecb004802802cea07782ab228Andy McFadden        float(x+w), float(y+h),
210441e847feb0e055ecb004802802cea07782ab228Andy McFadden        float(x),   float(y),
211441e847feb0e055ecb004802802cea07782ab228Andy McFadden        float(x+w), float(y),
212441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
213441e847feb0e055ecb004802802cea07782ab228Andy McFadden    const float uv[] = {
214441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f, 0.0f,
215441e847feb0e055ecb004802802cea07782ab228Andy McFadden        1.0f, 0.0f,
216441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f, 1.0f,
217441e847feb0e055ecb004802802cea07782ab228Andy McFadden        1.0f, 1.0f,
218441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
219441e847feb0e055ecb004802802cea07782ab228Andy McFadden    status_t err;
220441e847feb0e055ecb004802802cea07782ab228Andy McFadden
221587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    err = beforeDraw(texName, texMatrix, pos, uv, invert);
222441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err == NO_ERROR) {
223441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
224441e847feb0e055ecb004802802cea07782ab228Andy McFadden        err = afterDraw();
225441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
226441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return err;
227441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
228441e847feb0e055ecb004802802cea07782ab228Andy McFadden
229441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::drawTriangles(GLuint texName, const float* texMatrix,
230441e847feb0e055ecb004802802cea07782ab228Andy McFadden        const float* vertices, const float* texes, size_t count) const {
231441e847feb0e055ecb004802802cea07782ab228Andy McFadden    ALOGV("Program::drawTriangles texName=%d", texName);
232441e847feb0e055ecb004802802cea07782ab228Andy McFadden
233441e847feb0e055ecb004802802cea07782ab228Andy McFadden    status_t err;
234441e847feb0e055ecb004802802cea07782ab228Andy McFadden
235587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    err = beforeDraw(texName, texMatrix, vertices, texes, false);
236441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if (err == NO_ERROR) {
237441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDrawArrays(GL_TRIANGLES, 0, count);
238441e847feb0e055ecb004802802cea07782ab228Andy McFadden        err = afterDraw();
239441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
240441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return err;
241441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
242441e847feb0e055ecb004802802cea07782ab228Andy McFadden
243441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::beforeDraw(GLuint texName, const float* texMatrix,
244587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        const float* vertices, const float* texes, bool invert) const {
245441e847feb0e055ecb004802802cea07782ab228Andy McFadden    // Create an orthographic projection matrix based on viewport size.
246441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLint vp[4];
247441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glGetIntegerv(GL_VIEWPORT, vp);
248441e847feb0e055ecb004802802cea07782ab228Andy McFadden    float screenToNdc[16] = {
249441e847feb0e055ecb004802802cea07782ab228Andy McFadden        2.0f/float(vp[2]),  0.0f,               0.0f,   0.0f,
250441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f,               -2.0f/float(vp[3]), 0.0f,   0.0f,
251441e847feb0e055ecb004802802cea07782ab228Andy McFadden        0.0f,               0.0f,               1.0f,   0.0f,
252441e847feb0e055ecb004802802cea07782ab228Andy McFadden        -1.0f,              1.0f,               0.0f,   1.0f,
253441e847feb0e055ecb004802802cea07782ab228Andy McFadden    };
254587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    if (invert) {
255587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        screenToNdc[5] = -screenToNdc[5];
256587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden        screenToNdc[13] = -screenToNdc[13];
257587c6fefcd3c1d05c608ff511cf3534bc765256eAndy McFadden    }
258441e847feb0e055ecb004802802cea07782ab228Andy McFadden
259441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glUseProgram(mProgram);
260441e847feb0e055ecb004802802cea07782ab228Andy McFadden
261441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glVertexAttribPointer(maPositionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
262441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glVertexAttribPointer(maTextureCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, texes);
263441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glEnableVertexAttribArray(maPositionLoc);
264441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glEnableVertexAttribArray(maTextureCoordLoc);
265441e847feb0e055ecb004802802cea07782ab228Andy McFadden
266441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glUniformMatrix4fv(muMVPMatrixLoc, 1, GL_FALSE, screenToNdc);
267441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glUniformMatrix4fv(muGLCMatrixLoc, 1, GL_FALSE, texMatrix);
268441e847feb0e055ecb004802802cea07782ab228Andy McFadden
269441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glActiveTexture(GL_TEXTURE0);
270441e847feb0e055ecb004802802cea07782ab228Andy McFadden
271441e847feb0e055ecb004802802cea07782ab228Andy McFadden    switch (mProgramType) {
272441e847feb0e055ecb004802802cea07782ab228Andy McFadden    case PROGRAM_EXTERNAL_TEXTURE:
273441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texName);
274441e847feb0e055ecb004802802cea07782ab228Andy McFadden        break;
275441e847feb0e055ecb004802802cea07782ab228Andy McFadden    case PROGRAM_TEXTURE_2D:
276441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glBindTexture(GL_TEXTURE_2D, texName);
277441e847feb0e055ecb004802802cea07782ab228Andy McFadden        break;
278441e847feb0e055ecb004802802cea07782ab228Andy McFadden    default:
279441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("unexpected program type %d", mProgramType);
280441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
281441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
282441e847feb0e055ecb004802802cea07782ab228Andy McFadden
283441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glUniform1i(muTextureLoc, 0);
284441e847feb0e055ecb004802802cea07782ab228Andy McFadden
285441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLenum glErr;
286441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if ((glErr = glGetError()) != GL_NO_ERROR) {
287441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("GL error before draw: %#x", glErr);
288441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDisableVertexAttribArray(maPositionLoc);
289441e847feb0e055ecb004802802cea07782ab228Andy McFadden        glDisableVertexAttribArray(maTextureCoordLoc);
290441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
291441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
292441e847feb0e055ecb004802802cea07782ab228Andy McFadden
293441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
294441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
295441e847feb0e055ecb004802802cea07782ab228Andy McFadden
296441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Program::afterDraw() const {
297441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glDisableVertexAttribArray(maPositionLoc);
298441e847feb0e055ecb004802802cea07782ab228Andy McFadden    glDisableVertexAttribArray(maTextureCoordLoc);
299441e847feb0e055ecb004802802cea07782ab228Andy McFadden
300441e847feb0e055ecb004802802cea07782ab228Andy McFadden    GLenum glErr;
301441e847feb0e055ecb004802802cea07782ab228Andy McFadden    if ((glErr = glGetError()) != GL_NO_ERROR) {
302441e847feb0e055ecb004802802cea07782ab228Andy McFadden        ALOGE("GL error after draw: %#x", glErr);
303441e847feb0e055ecb004802802cea07782ab228Andy McFadden        return UNKNOWN_ERROR;
304441e847feb0e055ecb004802802cea07782ab228Andy McFadden    }
305441e847feb0e055ecb004802802cea07782ab228Andy McFadden
306441e847feb0e055ecb004802802cea07782ab228Andy McFadden    return NO_ERROR;
307441e847feb0e055ecb004802802cea07782ab228Andy McFadden}
308