Created
October 24, 2019 19:47
-
-
Save chris-hl/591de2b34d3af0792bc6aff36d23d7c7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <err.h> | |
#include <sys/time.h> | |
#include <g2d.h> | |
#include <wayland-egl.h> | |
#define GL_GLEXT_PROTOTYPES 1 | |
#include <EGL/egl.h> | |
#include <GLES2/gl2.h> | |
#include <GLES2/gl2ext.h> | |
#define RENDER_W 1920 | |
#define RENDER_H 1080 | |
static const char *vertShaderSrc = | |
"attribute vec4 g_vPosition;" | |
"attribute vec2 g_vTexCoord;" | |
"varying vec2 g_vVSTexCoord;" | |
"void main() {" | |
"gl_Position = g_vPosition;" | |
"g_vVSTexCoord = g_vTexCoord;" | |
"}"; | |
static const char *fragShaderSrc = | |
"precision mediump float;" | |
"uniform sampler2D tImage;" | |
"varying vec2 g_vVSTexCoord;" | |
"void main() {" | |
"vec4 color = texture2D(tImage, g_vVSTexCoord);" | |
// do something simple: swap R, B channels | |
"gl_FragColor = vec4(color.b, color.g, color.r, color.a);" | |
"}"; | |
static GLuint loadShader(GLint shaderType, const char* src) | |
{ | |
GLuint shader; | |
GLint status = GL_FALSE; | |
shader = glCreateShader(shaderType); | |
if (!shader) | |
err(-1, "glCreateShader() failed"); | |
glShaderSource(shader, 1, &src, NULL); | |
glCompileShader(shader); | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); | |
if (!status) | |
err(-1, "Errors while compiling shader"); | |
return shader; | |
} | |
static GLuint genTexture(const uint32_t w, const uint32_t h, GLint minmag_filter) | |
{ | |
GLuint t; | |
glGenTextures(1, &t); | |
glBindTexture(GL_TEXTURE_2D, t); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minmag_filter); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, minmag_filter); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | |
return t; | |
} | |
static void setupFramebuffer(uint32_t w, uint32_t h, int useVIVMap) | |
{ | |
GLuint frameBuffer; | |
GLuint renderT; | |
glGenFramebuffers(1, &frameBuffer); | |
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); | |
glGenTextures(1, &renderT); | |
glBindTexture(GL_TEXTURE_2D, renderT); | |
if (useVIVMap) { | |
struct g2d_buf *g2db; | |
void *vaddr; | |
uint32_t paddr; | |
g2db = g2d_alloc(4*w*h, 0); | |
vaddr = (uint8_t*)g2db->buf_vaddr; | |
paddr = g2db->buf_paddr; | |
glTexDirectVIVMap(GL_TEXTURE_2D, w, h, GL_RGBA, &vaddr, &paddr); | |
glTexDirectInvalidateVIV(GL_TEXTURE_2D); | |
} else { | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | |
} | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderT, 0); | |
GLenum fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); | |
if (fbstatus != GL_FRAMEBUFFER_COMPLETE) | |
err(-1, "glCheckFramebufferStatus() failed with %d", fbstatus); | |
} | |
static uint64_t get_microseconds() | |
{ | |
struct timeval time; | |
gettimeofday(&time, NULL); | |
return time.tv_sec * 1000000 + time.tv_usec; | |
} | |
int main(int argc, char **argv) | |
{ | |
struct wl_display *wl_display; | |
EGLDisplay eglDisplay; | |
EGLint eglMajVer, eglMinVer; | |
EGLConfig eglConfig; | |
EGLSurface eglSurface; | |
EGLContext eglContext; | |
GLuint num_config; | |
GLuint gl_hProgram; | |
GLuint gl_hVertShader; | |
GLuint gl_hFragShader; | |
GLuint gl_hTextureImage; | |
GLuint gl_hUniformImageLoc; | |
/* full plane 'quad' */ | |
float vertexPositions[] = { 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 0.0f, }; | |
GLuint gl_hVertexLoc; | |
float vertexTexCoords[] = { 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, }; | |
GLuint gl_hVertexTexLoc; | |
EGLint egl_attribs[] = { | |
EGL_RED_SIZE, 8, | |
EGL_GREEN_SIZE, 8, | |
EGL_BLUE_SIZE, 8, | |
EGL_ALPHA_SIZE, 8, | |
EGL_CONFORMANT, EGL_OPENGL_ES2_BIT, | |
EGL_NONE | |
}; | |
int useVIVMAP; | |
useVIVMAP = argc > 1; | |
wl_display = wl_display_connect(NULL); | |
eglDisplay = eglGetDisplay(wl_display); | |
if (eglDisplay == EGL_NO_DISPLAY) | |
err(-1, "eglGetDisplay failed"); | |
eglInitialize(eglDisplay, &eglMajVer, &eglMinVer); | |
eglBindAPI(EGL_OPENGL_ES_API); | |
if (!eglChooseConfig(eglDisplay, egl_attribs, &eglConfig, 1, &num_config)) | |
err(-1, "eglChooseConfig failed"); | |
EGLint egl_context_attrs[] = { | |
EGL_CONTEXT_MAJOR_VERSION, 2, | |
EGL_NONE | |
}; | |
eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, egl_context_attrs); | |
if (!eglContext) | |
err(-1, "eglCreateContext failed"); | |
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext); | |
setupFramebuffer(RENDER_W, RENDER_H, useVIVMAP); | |
glViewport(0, 0, RENDER_W, RENDER_H); | |
glCullFace(GL_BACK); | |
gl_hProgram = glCreateProgram(); | |
gl_hVertShader = loadShader(GL_VERTEX_SHADER, vertShaderSrc); | |
gl_hFragShader = loadShader(GL_FRAGMENT_SHADER, fragShaderSrc); | |
glAttachShader(gl_hProgram, gl_hVertShader); | |
glAttachShader(gl_hProgram, gl_hFragShader); | |
gl_hVertexLoc = 0; | |
glBindAttribLocation(gl_hProgram, gl_hVertexLoc, "g_vPosition"); | |
gl_hVertexTexLoc = 1; | |
glBindAttribLocation(gl_hProgram, gl_hVertexTexLoc, "g_vTexCoord"); | |
glLinkProgram(gl_hProgram); | |
GLint linkstatus; | |
glGetProgramiv(gl_hProgram, GL_LINK_STATUS, &linkstatus); | |
if (!linkstatus) | |
err(-1, "Program link errors"); | |
glUseProgram(gl_hProgram); | |
/* bind 'tImage' frag shader Sampler2D uniform to texture unit 1 */ | |
gl_hUniformImageLoc = glGetUniformLocation(gl_hProgram, "tImage"); | |
glActiveTexture(GL_TEXTURE1); | |
glUniform1i(gl_hUniformImageLoc, 1); | |
gl_hTextureImage = genTexture(RENDER_W, RENDER_H, GL_NEAREST); | |
/* bind vertices to vertex shader attributes */ | |
glVertexAttribPointer(gl_hVertexLoc, 3, GL_FLOAT, 0, 0, vertexPositions); | |
glEnableVertexAttribArray(gl_hVertexLoc); | |
glVertexAttribPointer(gl_hVertexTexLoc, 2, GL_FLOAT, 0, 0, vertexTexCoords); | |
glEnableVertexAttribArray(gl_hVertexTexLoc); | |
uint64_t start = get_microseconds(); | |
const uint32_t framecount = 60; | |
for (int frame = 0; frame < framecount; frame++) { | |
/* render something */ | |
glClear(GL_COLOR_BUFFER_BIT); | |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
glFlush(); | |
glFinish(); | |
/* DO SOMETHING HERE WITH CONTENTS OF RENDER BUFFER */ | |
}; | |
uint64_t end = get_microseconds(); | |
printf("frame useconds %u, fps %02.2f\n", (end-start)/framecount, (float)framecount / ((end-start) / 1000000.0)); | |
glUseProgram(0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment