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 65 Renderer* createES2Renderer() { 66 RendererES2* renderer = new RendererES2; 67 if (!renderer->init()) { 68 delete renderer; 69 return NULL; 70 } 71 return renderer; 72 } 73 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 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 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 114 float* RendererES2::mapOffsetBuf() { 115 return mOffsets; 116 } 117 118 void RendererES2::unmapOffsetBuf() { 119 } 120 121 float* RendererES2::mapTransformBuf() { 122 return mScaleRot; 123 } 124 125 void RendererES2::unmapTransformBuf() { 126 } 127 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