1 /*
2  * Copyright 2013 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 #include "gles3jni.h"
18 #include <EGL/egl.h>
19 
20 static const char VERTEX_SHADER[] =
21     "#version 100\n"
22     "uniform mat2 scaleRot;\n"
23     "uniform vec2 offset;\n"
24     "attribute vec2 pos;\n"
25     "attribute vec4 color;\n"
26     "varying vec4 vColor;\n"
27     "void main() {\n"
28     "    gl_Position = vec4(scaleRot*pos + offset, 0.0, 1.0);\n"
29     "    vColor = color;\n"
30     "}\n";
31 
32 static const char FRAGMENT_SHADER[] =
33     "#version 100\n"
34     "precision mediump float;\n"
35     "varying vec4 vColor;\n"
36     "void main() {\n"
37     "    gl_FragColor = vColor;\n"
38     "}\n";
39 
40 class RendererES2: public Renderer {
41 public:
42     RendererES2();
43     virtual ~RendererES2();
44     bool init();
45 
46 private:
47     virtual float* mapOffsetBuf();
48     virtual void unmapOffsetBuf();
49     virtual float* mapTransformBuf();
50     virtual void unmapTransformBuf();
51     virtual void draw(unsigned int numInstances);
52 
53     const EGLContext mEglContext;
54     GLuint mProgram;
55     GLuint mVB;
56     GLint mPosAttrib;
57     GLint mColorAttrib;
58     GLint mScaleRotUniform;
59     GLint mOffsetUniform;
60 
61     float mOffsets[2*MAX_INSTANCES];
62     float mScaleRot[4*MAX_INSTANCES];   // array of 2x2 column-major matrices
63 };
64 
createES2Renderer()65 Renderer* createES2Renderer() {
66     RendererES2* renderer = new RendererES2;
67     if (!renderer->init()) {
68         delete renderer;
69         return NULL;
70     }
71     return renderer;
72 }
73 
RendererES2()74 RendererES2::RendererES2()
75 :   mEglContext(eglGetCurrentContext()),
76     mProgram(0),
77     mVB(0),
78     mPosAttrib(-1),
79     mColorAttrib(-1),
80     mScaleRotUniform(-1),
81     mOffsetUniform(-1)
82 {}
83 
init()84 bool RendererES2::init() {
85     mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
86     if (!mProgram)
87         return false;
88     mPosAttrib = glGetAttribLocation(mProgram, "pos");
89     mColorAttrib = glGetAttribLocation(mProgram, "color");
90     mScaleRotUniform = glGetUniformLocation(mProgram, "scaleRot");
91     mOffsetUniform = glGetUniformLocation(mProgram, "offset");
92 
93     glGenBuffers(1, &mVB);
94     glBindBuffer(GL_ARRAY_BUFFER, mVB);
95     glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD[0], GL_STATIC_DRAW);
96 
97     ALOGV("Using OpenGL ES 2.0 renderer");
98     return true;
99 }
100 
~RendererES2()101 RendererES2::~RendererES2() {
102     /* The destructor may be called after the context has already been
103      * destroyed, in which case our objects have already been destroyed.
104      *
105      * If the context exists, it must be current. This only happens when we're
106      * cleaning up after a failed init().
107      */
108     if (eglGetCurrentContext() != mEglContext)
109         return;
110     glDeleteBuffers(1, &mVB);
111     glDeleteProgram(mProgram);
112 }
113 
mapOffsetBuf()114 float* RendererES2::mapOffsetBuf() {
115     return mOffsets;
116 }
117 
unmapOffsetBuf()118 void RendererES2::unmapOffsetBuf() {
119 }
120 
mapTransformBuf()121 float* RendererES2::mapTransformBuf() {
122     return mScaleRot;
123 }
124 
unmapTransformBuf()125 void RendererES2::unmapTransformBuf() {
126 }
127 
draw(unsigned int numInstances)128 void RendererES2::draw(unsigned int numInstances) {
129     glUseProgram(mProgram);
130 
131     glBindBuffer(GL_ARRAY_BUFFER, mVB);
132     glVertexAttribPointer(mPosAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos));
133     glVertexAttribPointer(mColorAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, rgba));
134     glEnableVertexAttribArray(mPosAttrib);
135     glEnableVertexAttribArray(mColorAttrib);
136 
137     for (unsigned int i = 0; i < numInstances; i++) {
138         glUniformMatrix2fv(mScaleRotUniform, 1, GL_FALSE, mScaleRot + 4*i);
139         glUniform2fv(mOffsetUniform, 1, mOffsets + 2*i);
140         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
141     }
142 }
143