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