166 lines
5.1 KiB
C++
166 lines
5.1 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>
|
|
|
|
#define STR(s) #s
|
|
#define STRV(s) STR(s)
|
|
|
|
#define POS_ATTRIB 0
|
|
#define COLOR_ATTRIB 1
|
|
#define SCALEROT_ATTRIB 2
|
|
#define OFFSET_ATTRIB 3
|
|
|
|
static const char VERTEX_SHADER[] =
|
|
"#version 300 es\n"
|
|
"layout(location = " STRV(POS_ATTRIB) ") in vec2 pos;\n"
|
|
"layout(location=" STRV(COLOR_ATTRIB) ") in vec4 color;\n"
|
|
"layout(location=" STRV(SCALEROT_ATTRIB) ") in vec4 scaleRot;\n"
|
|
"layout(location=" STRV(OFFSET_ATTRIB) ") in vec2 offset;\n"
|
|
"out vec4 vColor;\n"
|
|
"void main() {\n"
|
|
" mat2 sr = mat2(scaleRot.xy, scaleRot.zw);\n"
|
|
" gl_Position = vec4(sr*pos + offset, 0.0, 1.0);\n"
|
|
" vColor = color;\n"
|
|
"}\n";
|
|
|
|
static const char FRAGMENT_SHADER[] =
|
|
"#version 300 es\n"
|
|
"precision mediump float;\n"
|
|
"in vec4 vColor;\n"
|
|
"out vec4 outColor;\n"
|
|
"void main() {\n"
|
|
" outColor = vColor;\n"
|
|
"}\n";
|
|
|
|
class RendererES3: public Renderer {
|
|
public:
|
|
RendererES3();
|
|
virtual ~RendererES3();
|
|
bool init();
|
|
|
|
private:
|
|
enum {VB_INSTANCE, VB_SCALEROT, VB_OFFSET, VB_COUNT};
|
|
|
|
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[VB_COUNT];
|
|
GLuint mVBState;
|
|
};
|
|
|
|
Renderer* createES3Renderer() {
|
|
RendererES3* renderer = new RendererES3;
|
|
if (!renderer->init()) {
|
|
delete renderer;
|
|
return NULL;
|
|
}
|
|
return renderer;
|
|
}
|
|
|
|
RendererES3::RendererES3()
|
|
: mEglContext(eglGetCurrentContext()),
|
|
mProgram(0),
|
|
mVBState(0)
|
|
{
|
|
for (int i = 0; i < VB_COUNT; i++)
|
|
mVB[i] = 0;
|
|
}
|
|
|
|
bool RendererES3::init() {
|
|
mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
|
|
if (!mProgram)
|
|
return false;
|
|
|
|
glGenBuffers(VB_COUNT, mVB);
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_INSTANCE]);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD[0], GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
|
|
glBufferData(GL_ARRAY_BUFFER, MAX_INSTANCES * 4*sizeof(float), NULL, GL_DYNAMIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
|
|
glBufferData(GL_ARRAY_BUFFER, MAX_INSTANCES * 2*sizeof(float), NULL, GL_STATIC_DRAW);
|
|
|
|
glGenVertexArrays(1, &mVBState);
|
|
glBindVertexArray(mVBState);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_INSTANCE]);
|
|
glVertexAttribPointer(POS_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos));
|
|
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, rgba));
|
|
glEnableVertexAttribArray(POS_ATTRIB);
|
|
glEnableVertexAttribArray(COLOR_ATTRIB);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
|
|
glVertexAttribPointer(SCALEROT_ATTRIB, 4, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);
|
|
glEnableVertexAttribArray(SCALEROT_ATTRIB);
|
|
glVertexAttribDivisor(SCALEROT_ATTRIB, 1);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
|
|
glVertexAttribPointer(OFFSET_ATTRIB, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
|
|
glEnableVertexAttribArray(OFFSET_ATTRIB);
|
|
glVertexAttribDivisor(OFFSET_ATTRIB, 1);
|
|
|
|
ALOGV("Using OpenGL ES 3.0 renderer");
|
|
return true;
|
|
}
|
|
|
|
RendererES3::~RendererES3() {
|
|
/* 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;
|
|
glDeleteVertexArrays(1, &mVBState);
|
|
glDeleteBuffers(VB_COUNT, mVB);
|
|
glDeleteProgram(mProgram);
|
|
}
|
|
|
|
float* RendererES3::mapOffsetBuf() {
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_OFFSET]);
|
|
return (float*)glMapBufferRange(GL_ARRAY_BUFFER,
|
|
0, MAX_INSTANCES * 2*sizeof(float),
|
|
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
|
}
|
|
|
|
void RendererES3::unmapOffsetBuf() {
|
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
}
|
|
|
|
float* RendererES3::mapTransformBuf() {
|
|
glBindBuffer(GL_ARRAY_BUFFER, mVB[VB_SCALEROT]);
|
|
return (float*)glMapBufferRange(GL_ARRAY_BUFFER,
|
|
0, MAX_INSTANCES * 4*sizeof(float),
|
|
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
|
}
|
|
|
|
void RendererES3::unmapTransformBuf() {
|
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
}
|
|
|
|
void RendererES3::draw(unsigned int numInstances) {
|
|
glUseProgram(mProgram);
|
|
glBindVertexArray(mVBState);
|
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, numInstances);
|
|
}
|