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 #define STR(s) #s
21 #define STRV(s) STR(s)
22 
23 #define POS_ATTRIB 0
24 #define COLOR_ATTRIB 1
25 #define SCALEROT_ATTRIB 2
26 #define OFFSET_ATTRIB 3
27 
28 static const char VERTEX_SHADER[] =
29     "#version 300 es\n"
30     "layout(location = " STRV(POS_ATTRIB) ") in vec2 pos;\n"
31     "layout(location=" STRV(COLOR_ATTRIB) ") in vec4 color;\n"
32     "layout(location=" STRV(SCALEROT_ATTRIB) ") in vec4 scaleRot;\n"
33     "layout(location=" STRV(OFFSET_ATTRIB) ") in vec2 offset;\n"
34     "out vec4 vColor;\n"
35     "void main() {\n"
36     "    mat2 sr = mat2(scaleRot.xy, scaleRot.zw);\n"
37     "    gl_Position = vec4(sr*pos + offset, 0.0, 1.0);\n"
38     "    vColor = color;\n"
39     "}\n";
40 
41 static const char FRAGMENT_SHADER[] =
42     "#version 300 es\n"
43     "precision mediump float;\n"
44     "in vec4 vColor;\n"
45     "out vec4 outColor;\n"
46     "void main() {\n"
47     "    outColor = vColor;\n"
48     "}\n";
49 
50 class RendererES3: public Renderer {
51 public:
52     RendererES3();
53     virtual ~RendererES3();
54     bool init();
55 
56 private:
57     enum {VB_INSTANCE, VB_SCALEROT, VB_OFFSET, VB_COUNT};
58 
59     virtual float* mapOffsetBuf();
60     virtual void unmapOffsetBuf();
61     virtual float* mapTransformBuf();
62     virtual void unmapTransformBuf();
63     virtual void draw(unsigned int numInstances);
64 
65     const EGLContext mEglContext;
66     GLuint mProgram;
67     GLuint mVB[VB_COUNT];
68     GLuint mVBState;
69 };
70 
createES3Renderer()71 Renderer* createES3Renderer() {
72     RendererES3* renderer = new RendererES3;
73     if (!renderer->init()) {
74         delete renderer;
75         return NULL;
76     }
77     return renderer;
78 }
79 
RendererES3()80 RendererES3::RendererES3()
81 :   mEglContext(eglGetCurrentContext()),
82     mProgram(0),
83     mVBState(0)
84 {
85     for (int i = 0; i < VB_COUNT; i++)
86         mVB[i] = 0;
87 }
88 
init()89 bool RendererES3::init() {
90     mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
91     if (!mProgram)
92         return false;
93 
94     glGenBuffers(VB_COUNT, mVB);
95     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_INSTANCE]);
96     glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD[0], GL_STATIC_DRAW);
97     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
98     glBufferData(GL_ARRAY_BUFFER, MAX_INSTANCES * 4*sizeof(float), NULL, GL_DYNAMIC_DRAW);
99     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
100     glBufferData(GL_ARRAY_BUFFER, MAX_INSTANCES * 2*sizeof(float), NULL, GL_STATIC_DRAW);
101 
102     glGenVertexArrays(1, &mVBState);
103     glBindVertexArray(mVBState);
104 
105     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_INSTANCE]);
106     glVertexAttribPointer(POS_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos));
107     glVertexAttribPointer(COLOR_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, rgba));
108     glEnableVertexAttribArray(POS_ATTRIB);
109     glEnableVertexAttribArray(COLOR_ATTRIB);
110 
111     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
112     glVertexAttribPointer(SCALEROT_ATTRIB, 4, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);
113     glEnableVertexAttribArray(SCALEROT_ATTRIB);
114     glVertexAttribDivisor(SCALEROT_ATTRIB, 1);
115 
116     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
117     glVertexAttribPointer(OFFSET_ATTRIB, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
118     glEnableVertexAttribArray(OFFSET_ATTRIB);
119     glVertexAttribDivisor(OFFSET_ATTRIB, 1);
120 
121     ALOGV("Using OpenGL ES 3.0 renderer");
122     return true;
123 }
124 
~RendererES3()125 RendererES3::~RendererES3() {
126     /* The destructor may be called after the context has already been
127      * destroyed, in which case our objects have already been destroyed.
128      *
129      * If the context exists, it must be current. This only happens when we're
130      * cleaning up after a failed init().
131      */
132     if (eglGetCurrentContext() != mEglContext)
133         return;
134     glDeleteVertexArrays(1, &mVBState);
135     glDeleteBuffers(VB_COUNT, mVB);
136     glDeleteProgram(mProgram);
137 }
138 
mapOffsetBuf()139 float* RendererES3::mapOffsetBuf() {
140     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
141     return (float*)glMapBufferRange(GL_ARRAY_BUFFER,
142             0, MAX_INSTANCES * 2*sizeof(float),
143             GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
144 }
145 
unmapOffsetBuf()146 void RendererES3::unmapOffsetBuf() {
147     glUnmapBuffer(GL_ARRAY_BUFFER);
148 }
149 
mapTransformBuf()150 float* RendererES3::mapTransformBuf() {
151     glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
152     return (float*)glMapBufferRange(GL_ARRAY_BUFFER,
153             0, MAX_INSTANCES * 4*sizeof(float),
154             GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
155 }
156 
unmapTransformBuf()157 void RendererES3::unmapTransformBuf() {
158     glUnmapBuffer(GL_ARRAY_BUFFER);
159 }
160 
draw(unsigned int numInstances)161 void RendererES3::draw(unsigned int numInstances) {
162     glUseProgram(mProgram);
163     glBindVertexArray(mVBState);
164     glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, numInstances);
165 }
166