| /* |
| * Copyright 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "gles3jni.h" |
| #include <EGL/egl.h> |
| |
| static const char VERTEX_SHADER[] = |
| "#version 100\n" |
| "uniform mat2 scaleRot;\n" |
| "uniform vec2 offset;\n" |
| "attribute vec2 pos;\n" |
| "attribute vec4 color;\n" |
| "varying vec4 vColor;\n" |
| "void main() {\n" |
| " gl_Position = vec4(scaleRot*pos + offset, 0.0, 1.0);\n" |
| " vColor = color;\n" |
| "}\n"; |
| |
| static const char FRAGMENT_SHADER[] = |
| "#version 100\n" |
| "precision mediump float;\n" |
| "varying vec4 vColor;\n" |
| "void main() {\n" |
| " gl_FragColor = vColor;\n" |
| "}\n"; |
| |
| class RendererES2: public Renderer { |
| public: |
| RendererES2(); |
| virtual ~RendererES2(); |
| bool init(); |
| |
| private: |
| virtual float* mapOffsetBuf(); |
| virtual void unmapOffsetBuf(); |
| virtual float* mapTransformBuf(); |
| virtual void unmapTransformBuf(); |
| virtual void draw(unsigned int numInstances); |
| |
| const EGLContext mEglContext; |
| GLuint mProgram; |
| GLuint mVB; |
| GLint mPosAttrib; |
| GLint mColorAttrib; |
| GLint mScaleRotUniform; |
| GLint mOffsetUniform; |
| |
| float mOffsets[2*MAX_INSTANCES]; |
| float mScaleRot[4*MAX_INSTANCES]; // array of 2x2 column-major matrices |
| }; |
| |
| Renderer* createES2Renderer() { |
| RendererES2* renderer = new RendererES2; |
| if (!renderer->init()) { |
| delete renderer; |
| return NULL; |
| } |
| return renderer; |
| } |
| |
| RendererES2::RendererES2() |
| : mEglContext(eglGetCurrentContext()), |
| mProgram(0), |
| mVB(0), |
| mPosAttrib(-1), |
| mColorAttrib(-1), |
| mScaleRotUniform(-1), |
| mOffsetUniform(-1) |
| {} |
| |
| bool RendererES2::init() { |
| mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER); |
| if (!mProgram) |
| return false; |
| mPosAttrib = glGetAttribLocation(mProgram, "pos"); |
| mColorAttrib = glGetAttribLocation(mProgram, "color"); |
| mScaleRotUniform = glGetUniformLocation(mProgram, "scaleRot"); |
| mOffsetUniform = glGetUniformLocation(mProgram, "offset"); |
| |
| glGenBuffers(1, &mVB); |
| glBindBuffer(GL_ARRAY_BUFFER, mVB); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD[0], GL_STATIC_DRAW); |
| |
| ALOGV("Using OpenGL ES 2.0 renderer"); |
| return true; |
| } |
| |
| RendererES2::~RendererES2() { |
| /* The destructor may be called after the context has already been |
| * destroyed, in which case our objects have already been destroyed. |
| * |
| * If the context exists, it must be current. This only happens when we're |
| * cleaning up after a failed init(). |
| */ |
| if (eglGetCurrentContext() != mEglContext) |
| return; |
| glDeleteBuffers(1, &mVB); |
| glDeleteProgram(mProgram); |
| } |
| |
| float* RendererES2::mapOffsetBuf() { |
| return mOffsets; |
| } |
| |
| void RendererES2::unmapOffsetBuf() { |
| } |
| |
| float* RendererES2::mapTransformBuf() { |
| return mScaleRot; |
| } |
| |
| void RendererES2::unmapTransformBuf() { |
| } |
| |
| void RendererES2::draw(unsigned int numInstances) { |
| glUseProgram(mProgram); |
| |
| glBindBuffer(GL_ARRAY_BUFFER, mVB); |
| glVertexAttribPointer(mPosAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos)); |
| glVertexAttribPointer(mColorAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, rgba)); |
| glEnableVertexAttribArray(mPosAttrib); |
| glEnableVertexAttribArray(mColorAttrib); |
| |
| for (unsigned int i = 0; i < numInstances; i++) { |
| glUniformMatrix2fv(mScaleRotUniform, 1, GL_FALSE, mScaleRot + 4*i); |
| glUniform2fv(mOffsetUniform, 1, mOffsets + 2*i); |
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| } |
| } |