Skip to content

Instantly share code, notes, and snippets.

Created December 14, 2012 21:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/4288977 to your computer and use it in GitHub Desktop.
Save anonymous/4288977 to your computer and use it in GitHub Desktop.
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglext_brcm.h>
#include <stdio.h>
#include <assert.h>
#include "shared.h"
static const char *vShaderSrc =
"attribute vec4 a_position; \n"
"void main() \n"
"{ \n"
" gl_Position = a_position; \n"
"} \n";
static const char *fShaderSrc =
"precision mediump float; \n"
"const vec4 color = vec4(1.0, 0.0, 0.0, 1.0); \n"
"void main() \n"
"{ \n"
" gl_FragColor = color; \n"
"} \n";
#ifndef WINDOW
#define WINDOW 0
#endif
struct simple_program_t
{
GLint id;
GLint position_attr_location;
};
struct simple_program_t create_simple_program()
{
struct simple_program_t program;
program.id = create_gl_program(vShaderSrc, fShaderSrc);
program.position_attr_location = glGetAttribLocation(program.id, "a_position");
return program;
}
struct vertex_t {
GLfloat position[3];
};
void draw(const struct simple_program_t p)
{
glClear(GL_COLOR_BUFFER_BIT);
// Drawing vectors
static const struct vertex_t vertex_data[] = {
{{-1.0f, -1.0f, 0.0f}},
{{ 0.0f, 1.0f, 0.0f}},
{{ 1.0f, -1.0f, 0.0f}},
};
glVertexAttribPointer(p.position_attr_location, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex_t),
&vertex_data[0].position);
glEnableVertexAttribArray(p.position_attr_location);
glDrawArrays(GL_TRIANGLES, 0, 3);
glFinish();
}
int main(int argc, char** argv)
{
bcm_host_init();
EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLint attribList[] =
{
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, EGL_DONT_CARE,
EGL_SAMPLE_BUFFERS, 0,
EGL_NONE
};
Context ctx = create_context(EGL_NO_DISPLAY, attribList, contextAttribs);
EGLint width;
EGLint height;
#if (WINDOW)
ctx.surface = eglCreateWindowSurface(ctx.display, ctx.config, create_native_window(&width, &height), NULL);
#else
int global_image[5];
width = 480;
height = 360;
ctx.surface = create_surface_from_shared_pixmap(ctx.display, ctx.config, global_image, width, height);
#endif
assert(ctx.surface != EGL_NO_SURFACE);
eglMakeCurrent(ctx.display, ctx.surface, ctx.surface, ctx.context);
// Creating program and cleaning up opengl
struct simple_program_t program = create_simple_program();
glUseProgram(program.id);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glClearColor(0.2f, 0.2f, 0.4f, 1.0f);
glViewport(0, 0, width, height);
glCullFace(GL_FRONT_AND_BACK);
int done = 0;
while (!done) {
draw(program);
EGLint attrib[] =
{
EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE,
EGL_LOCK_USAGE_HINT_KHR, EGL_WRITE_SURFACE_BIT_KHR, // | EGL_READ_SURFACE_BIT_KHR,
EGL_NONE
};
eglWaitClient();
assert(eglLockSurfaceKHR(ctx.display, ctx.surface, attrib));
unsigned char *data = 0;
int pitch = 0;
int pixsize = 0;
int origin = 0;
int r_offset = 0, g_offset = 0, b_offset = 0, a_offset = 0;
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_POINTER_KHR, (EGLint*)&data);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_PITCH_KHR, &pitch);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_PIXEL_SIZE_KHR, &pixsize);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_ORIGIN_KHR, &origin);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_PIXEL_RED_OFFSET_KHR, &r_offset);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR, &g_offset);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR, &b_offset);
eglQuerySurface(ctx.display, ctx.surface, EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR, &a_offset);
// assert(eglUnlockSurfaceKHR(ctx.display, ctx.surface));
eglSwapBuffers(ctx.display, ctx.surface);
}
destroy_context(&ctx);
destroy_native_window();
return 0;
}
CC=gcc
LIBS = -lGLESv2 -lEGL -lbcm_host -L$(SDKSTAGE)/opt/vc/lib
INC_DIRS = -I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
DEFINES = -D EGL_EGLEXT_PROTOTYPES -D GL_GLEXT_PROTOTYPES -DWINDOW=1
lock: lock.o shared.o
$(CC) $(INC_DIRS) $(LIBS) $(DEFINES) $? -o $@
%.o: %.c
$(CC) $(INC_DIRS) $(LIBS) $(DEFINES) -c $? -o $@
clean:
rm -rf *.o
rm -rf lock
#include "shared.h"
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglext_brcm.h>
#include <assert.h>
#include <stdio.h>
#define EGL_PIXEL_FORMAT_ARGB_8888_PRE_BRCM 0
#define EGL_PIXEL_FORMAT_ARGB_8888_BRCM 1
#define EGL_PIXEL_FORMAT_XRGB_8888_BRCM 2
#define EGL_PIXEL_FORMAT_RGB_565_BRCM 3
#define EGL_PIXEL_FORMAT_A_8_BRCM 4
#define EGL_PIXEL_FORMAT_RENDER_GL_BRCM (1 << 3)
#define EGL_PIXEL_FORMAT_RENDER_GLES_BRCM (1 << 4)
#define EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM (1 << 5)
#define EGL_PIXEL_FORMAT_RENDER_VG_BRCM (1 << 6)
#define EGL_PIXEL_FORMAT_RENDER_MASK_BRCM 0x78
#define EGL_PIXEL_FORMAT_VG_IMAGE_BRCM (1 << 7)
#define EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM (1 << 8)
#define EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM (1 << 9)
#define EGL_PIXEL_FORMAT_TEXTURE_MASK_BRCM 0x380
#define EGL_PIXEL_FORMAT_USAGE_MASK_BRCM 0x3f8
EGLSurface create_surface_from_shared_pixmap(EGLDisplay display, EGLConfig config, EGLint* global_image, int width, int height) {
EGLint pixel_format = EGL_PIXEL_FORMAT_ARGB_8888_BRCM;
EGLint rt;
eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &rt);
if (rt & EGL_OPENGL_ES_BIT) {
pixel_format |= EGL_PIXEL_FORMAT_RENDER_GLES_BRCM;
pixel_format |= EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM;
}
if (rt & EGL_OPENGL_ES2_BIT) {
pixel_format |= EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM;
pixel_format |= EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
}
if (rt & EGL_OPENVG_BIT) {
pixel_format |= EGL_PIXEL_FORMAT_RENDER_VG_BRCM;
pixel_format |= EGL_PIXEL_FORMAT_VG_IMAGE_BRCM;
}
if (rt & EGL_OPENGL_BIT) {
pixel_format |= EGL_PIXEL_FORMAT_RENDER_GL_BRCM;
}
global_image[0] = 0;
global_image[1] = 0;
global_image[2] = width;
global_image[3] = height;
global_image[4] = pixel_format;
eglCreateGlobalImageBRCM(width, height, global_image[4], 0, width*4, global_image);
EGLint attrs[] = {
EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB,
EGL_VG_ALPHA_FORMAT, pixel_format & EGL_PIXEL_FORMAT_ARGB_8888_PRE_BRCM ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE,
EGL_NONE
};
EGLSurface surface = eglCreatePixmapSurface(display, config, (EGLNativePixmapType)global_image, attrs);
eglFlushBRCM();
return surface;
}
EGLImageKHR create_image_from_shared_pixmap(EGLDisplay display, EGLint* global_image) {
assert (eglQueryGlobalImageBRCM(global_image, global_image+2));
EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)global_image, NULL);
assert (image != EGL_NO_IMAGE_KHR);
return image;
}
GLuint create_texture_from_image(EGLImageKHR image)
{
GLuint tid;
glGenTextures(1, &tid);
glBindTexture(GL_TEXTURE_2D, tid);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
return tid;
}
GLuint create_texture_from_shared_pixmap(EGLDisplay display, EGLint* global_image) {
assert (eglQueryGlobalImageBRCM(global_image, global_image+2));
EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)global_image, NULL);
assert (image != EGL_NO_IMAGE_KHR);
GLuint tid;
glGenTextures(1, &tid);
glBindTexture(GL_TEXTURE_2D, tid);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
eglDestroyImageKHR(display, image);
return tid;
}
Context create_context(EGLDisplay display, EGLint attribList[], EGLint contextAttribs[])
{
Context ctx;
EGLint majorVersion;
EGLint minorVersion;
// Get Display
if (display == EGL_NO_DISPLAY)
ctx.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(ctx.display != EGL_NO_DISPLAY);
// Initialize EGL
assert(eglInitialize(ctx.display, &majorVersion, &minorVersion));
// Get configs
assert(eglGetConfigs(ctx.display, NULL, 0, &ctx.numConfigs));
// Choose config
assert(eglChooseConfig(ctx.display, attribList, &ctx.config, 1, &ctx.numConfigs));
// Create a GL context
ctx.context = eglCreateContext(ctx.display, ctx.config, EGL_NO_CONTEXT, contextAttribs);
assert(ctx.context != EGL_NO_CONTEXT);
return ctx;
}
void destroy_context(Context *ctx)
{
if (ctx->display == EGL_NO_DISPLAY)
return;
eglMakeCurrent(ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(ctx->display, ctx->context);
eglDestroySurface(ctx->display, ctx->surface);
eglTerminate(ctx->display);
ctx->context = EGL_NO_CONTEXT;
ctx->display = EGL_NO_DISPLAY;
ctx->surface = EGL_NO_SURFACE;
}
void context_make_current(Context *ctx)
{
eglMakeCurrent(ctx->display, ctx->surface, ctx->surface, ctx->context);
}
static EGL_DISPMANX_WINDOW_T dispman_window;
static DISPMANX_ELEMENT_HANDLE_T dispman_element;
static DISPMANX_DISPLAY_HANDLE_T dispman_display;
static DISPMANX_UPDATE_HANDLE_T dispman_update;
EGLNativeWindowType create_native_window(int *width, int *height)
{
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
uint32_t display_width;
uint32_t display_height;
uint32_t success;
success = graphics_get_display_size(0 /* LCD */, &display_width, &display_height);
if (success < 0)
{
return 0;
}
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = display_width;
dst_rect.height = display_height;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = display_width << 16;
src_rect.height = display_height << 16;
dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
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*/, 0 /*transform*/);
dispman_window.element = dispman_element;
dispman_window.width = display_width;
dispman_window.height = display_height;
vc_dispmanx_update_submit_sync(dispman_update);
*width = display_width;
*height = display_height;
return &dispman_window;
}
void destroy_native_window()
{
vc_dispmanx_element_remove(dispman_update, dispman_window.element);
vc_dispmanx_display_close(dispman_display);
}
static GLuint compile_shader(GLenum type, const char *shaderSrc)
{
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if (shader == 0)
return 0;
glShaderSource(shader, 1, &shaderSrc, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 0) {
char infoLog[infoLen];
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
fprintf(stderr, infoLog);
fflush(stderr);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
GLint create_gl_program(const char* vShaderSrc, const char* fShaderSrc)
{
GLint program;
// Compiling shaders
GLuint vShader, fShader;
vShader = compile_shader(GL_VERTEX_SHADER, vShaderSrc);
if (!vShader)
return 0;
fShader = compile_shader(GL_FRAGMENT_SHADER, fShaderSrc);
if (!fShader) {
glDeleteShader(vShader);
return 0;
}
// Linking
program = glCreateProgram();
if (!program)
return 0;
glAttachShader(program, vShader);
glAttachShader(program, fShader);
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 0) {
char infoLog[infoLen];
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
fprintf(stderr, infoLog);
fflush(stderr);
}
glDeleteProgram(program);
return 0;
}
glDeleteShader(vShader);
glDeleteShader(fShader);
return program;
}
#ifndef SHARED_H
#define SHARED_H
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
typedef struct {
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig config;
EGLint numConfigs;
} Context;
Context create_context(EGLDisplay display, EGLint attribList[], EGLint contextAttribs[]);
EGLSurface create_surface_from_shared_pixmap(EGLDisplay display, EGLConfig config, EGLint* global_image, int width, int height);
GLuint create_texture_from_shared_pixmap(EGLDisplay display, EGLint* global_image);
EGLImageKHR create_image_from_shared_pixmap(EGLDisplay display, EGLint* global_image);
GLuint create_texture_from_image(EGLImageKHR image);
EGLNativeWindowType create_native_window(int* width, int* height);
void context_make_current(Context* context);
void destroy_context(Context* context);
void destroy_native_window();
GLint create_gl_program(const char* vertexShaderSource, const char* fragmentShaderSource);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment