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 71 Renderer* createES3Renderer() { 72 RendererES3* renderer = new RendererES3; 73 if (!renderer->init()) { 74 delete renderer; 75 return NULL; 76 } 77 return renderer; 78 } 79 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 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 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 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 146 void RendererES3::unmapOffsetBuf() { 147 glUnmapBuffer(GL_ARRAY_BUFFER); 148 } 149 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 157 void RendererES3::unmapTransformBuf() { 158 glUnmapBuffer(GL_ARRAY_BUFFER); 159 } 160 161 void RendererES3::draw(unsigned int numInstances) { 162 glUseProgram(mProgram); 163 glBindVertexArray(mVBState); 164 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, numInstances); 165 } 166