143 lines
4.0 KiB
C++
143 lines
4.0 KiB
C++
/*
|
|
* 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);
|
|
}
|
|
}
|