Skip to content

Instantly share code, notes, and snippets.

@jwatte
Created August 16, 2014 05:19
Show Gist options
  • Save jwatte/73e5e0e9f5bf0de5eadb to your computer and use it in GitHub Desktop.
Save jwatte/73e5e0e9f5bf0de5eadb to your computer and use it in GitHub Desktop.
Problem C++ file for Raspberry Pi
#include "All.h"
#include <VG/openvg.h>
#include <VG/vgu.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <bcm_host.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <map>
#include <string>
struct EGLState {
EGLState() {
width = 0;
height = 0;
display = 0;
surface = 0;
context = 0;
startTime = 0;
nFrames = 0;
prevFps = 0;
}
uint32_t width;
uint32_t height;
EGL_DISPMANX_WINDOW_T window;
EGLDisplay display;
EGLSurface surface;
EGLContext context;
double startTime;
float prevFps;
int nFrames;
GLuint program;
GLuint uMatrix;
GLuint uTexture;
};
static void InitWindow(EGLState *state) {
int32_t success = 0;
EGLBoolean result;
EGLint num_config;
DISPMANX_ELEMENT_HANDLE_T dispman_element;
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
static const EGLint attribute_list[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
// No depth needed for OpenVG
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLConfig config = 0;
// get an EGL display connection
state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(state->display != EGL_NO_DISPLAY);
// initialize the EGL display connection
result = eglInitialize(state->display, NULL, NULL);
assert(EGL_FALSE != result);
// bind GLES2 API
eglBindAPI(EGL_OPENGL_ES_API);
// get an appropriate EGL frame buffer configuration
result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
assert(EGL_FALSE != result);
// create an EGL rendering context
state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, NULL);
assert(state->context != EGL_NO_CONTEXT);
// create an EGL window surface
success = graphics_get_display_size(0, &state->width, &state->height);
assert(success >= 0);
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = state->width;
dst_rect.height = state->height;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = state->width << 16;
src_rect.height = state->height << 16;
dispman_display = vc_dispmanx_display_open(0);
dispman_update = vc_dispmanx_update_start(0);
dispman_element = vc_dispmanx_element_add(
dispman_update,
dispman_display,
0 /*layer */ ,
&dst_rect,
0 /*src */ ,
&src_rect,
DISPMANX_PROTECTION_NONE,
0 /*alpha */ ,
0 /*clamp */ ,
DISPMANX_NO_ROTATE /*transform */ );
state->window.element = dispman_element;
state->window.width = state->width;
state->window.height = state->height;
vc_dispmanx_update_submit_sync(dispman_update);
state->surface = eglCreateWindowSurface(state->display, config, &state->window, NULL);
assert(state->surface != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
assert(EGL_FALSE != result);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
GLCHECK();
fprintf(stderr, "Created display surface.\n");
}
Display::Display() {
state = new EGLState();
bcm_host_init();
InitWindow(state);
LoadShaders();
state->startTime = Time();
state->prevFps = 0.0;
}
Display::~Display() {
eglMakeCurrent(state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(state->display, state->surface);
eglDestroyContext(state->display, state->context);
eglTerminate(state->display);
delete state;
state = NULL;
}
static GLuint load_shader(char const *name, GLuint type) {
GLuint shader = glCreateShader(type);
fprintf(stderr, "%s (0x%x) = 0x%x\n", name, type, shader);
GLCHECK();
assert(shader != 0);
FILE *f = fopen(name, "rb");
if (!f) {
fprintf(stderr, "could not find required shader %s\n", name);
exit(1);
}
fseek(f, 0, 2);
long l = ftell(f);
fseek(f, 0, 0);
char *data = new char[l+1];
fread(data, 1, l, f);
data[l] = 0;
fclose(f);
glShaderSource(shader, 1, const_cast<char const **>(&data), nullptr);
delete[] data;
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infolen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infolen);
if (infolen > 1) {
char *info = new char[infolen+1];
glGetShaderInfoLog(shader, infolen, nullptr, info);
info[infolen] = 0;
fprintf(stderr, "%s:1: compile error:\n%s\n", name, info);
delete[] info;
} else {
fprintf(stderr, "%s:1: unknown compile error\n", name);
}
exit(1);
}
return shader;
}
void Display::LoadShaders() {
GLuint vShader = load_shader("vertex.glsl", GL_VERTEX_SHADER);
GLuint fShader = load_shader("fragment.glsl", GL_FRAGMENT_SHADER);
state->program = glCreateProgram();
GLCHECK();
assert(state->program != 0);
glAttachShader(state->program, vShader);
glAttachShader(state->program, fShader);
glBindAttribLocation(state->program, 0, "attrPos");
glBindAttribLocation(state->program, 1, "attrUV");
glLinkProgram(state->program);
GLint linked = 0;
glGetProgramiv(state->program, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infolen = 0;
glGetProgramiv(state->program, GL_INFO_LOG_LENGTH, &infolen);
if (infolen > 1) {
char *info = new char[infolen+1];
glGetProgramInfoLog(state->program, infolen, nullptr, info);
info[infolen] = 0;
fprintf(stderr, "GLES program link error:\n%s\n", info);
delete[] info;
} else {
fprintf(stderr, "GLES unknown program link error.\n");
}
exit(1);
}
state->uMatrix = glGetUniformLocation(state->program, "uMatrix");
state->uTexture = glGetUniformLocation(state->program, "uTexture");
glUniform1i(state->uTexture, 0); // texture unit 0
GLCHECK();
}
int Display::Width() {
return (int)state->width;
}
int Display::Height() {
return (int)state->height;
}
void Display::Begin() {
GLCHECK();
glDisable(GL_BLEND);
glViewport(0, 0, Width(), Height());
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
float mat[16] = {
2.0f / Width(), 0, 0, -1,
0, -2.0f / Height(), 0, -1,
0, 0, 1, 0,
0, 0, 0, 1,
};
glUniformMatrix4fv(state->uMatrix, 1, GL_FALSE, mat);
GLCHECK();
}
void Display::Flip() {
GLCHECK();
eglSwapBuffers(state->display, state->surface);
++state->nFrames;
}
double Display::Time() {
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_sec + 1e-9*tv.tv_nsec;
}
float Display::Fps() {
double now = Time();
if (now - state->startTime >= 1.25) {
state->prevFps = state->nFrames / (now - state->startTime);
state->nFrames = 0;
state->startTime = now;
}
return state->prevFps;
}
void gl_check(char const *file, int line, char const *func) {
GLuint err = glGetError();
if (err) {
fprintf(stderr, "%s:%d: gl error 0x%x in %s\n", file, line, err, func);
abort();
}
}
static std::map<std::string, GLuint> textures;
static bool bgraKnown = false;
static bool hasBgra = false;
#if !defined(GL_BGRA_EXT)
#define GL_BGRA_EXT ((GLenum)0x80E1)
#endif
unsigned int Display::LoadTexture(char const *name) {
auto ptr(textures.find(name));
if (ptr != textures.end()) {
return (*ptr).second;
}
if (!bgraKnown) {
bgraKnown = true;
hasBgra = strstr((char const *)glGetString(GL_EXTENSIONS), "GL_EXT_texture_format_BGRA8888") != NULL;
if (hasBgra) {
fprintf(stderr, "has GL_EXT_texture_format_BGRA8888\n");
}
}
FILE *f = fopen(name, "rb");
if (!f) {
fprintf(stderr, "Could not load texture: %s\n", name);
exit(1);
}
unsigned char hdr[18];
fread(hdr, 1, 18, f);
size_t bpp = 0;
if (hdr[2] == 2) {
bpp = 4;
} else if (hdr[2] == 3) {
bpp = 1;
}
fseek(f, hdr[0], 1);
unsigned int width = hdr[12] + (hdr[13] << 8);
unsigned int height = hdr[14] + (hdr[15] << 8);
if (bpp == 4 && hdr[16] == 24) {
bpp = 3;
}
fprintf(stderr, "%s: %dx%d@%d\n", name, width, height, bpp*8);
unsigned char *data = new unsigned char[width * height * bpp];
fread(data, 1, width*height*bpp, f);
fclose(f);
GLuint tex = 0;
GLCHECK();
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLCHECK();
GLuint fmt = (bpp == 1) ? GL_LUMINANCE : (bpp == 3) ? GL_RGB : GL_RGBA;
if (bpp == 4 && hasBgra) {
fmt = GL_BGRA_EXT;
} else if (bpp > 1) {
unsigned char *ptr = data;
size_t n = width * height;
while (n-- > 0) {
unsigned char sw = ptr[0];
ptr[0] = ptr[2];
ptr[2] = sw;
ptr += bpp;
}
}
glTexImage2D(GL_TEXTURE_2D, 0, fmt, width, height, 0, fmt, GL_UNSIGNED_BYTE, data);
GLCHECK();
glGenerateMipmap(GL_TEXTURE_2D);
GLCHECK();
textures[name] = tex;
glBindTexture(GL_TEXTURE_2D, 0);
delete[] data;
return tex;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment