Skip to content

Instantly share code, notes, and snippets.

@ajstarks
Created July 27, 2012 04:33
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ajstarks/3186193 to your computer and use it in GitHub Desktop.
Save ajstarks/3186193 to your computer and use it in GitHub Desktop.
// shapes: minimal program to explore OpenVG
// Anthony Starks (ajstarks@gmail.com)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "EGL/egl.h"
#include "GLES/gl.h"
typedef struct
{
uint32_t screen_width;
uint32_t screen_height;
// OpenGL|ES objects
EGLDisplay display;
EGLSurface surface;
EGLContext context;
} STATE_T;
static void exit_func(void);
static STATE_T _state, *state=&_state;
// init_ogl sets the display, OpenGL|ES context and screen information
// state holds the OGLES model information
static void init_ogl(STATE_T *state) {
int32_t success = 0;
EGLBoolean result;
EGLint num_config;
static EGL_DISPMANX_WINDOW_T nativewindow;
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,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
EGLConfig config;
// 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 OpenVG API
eglBindAPI(EGL_OPENVG_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 /* LCD */, &state->screen_width, &state->screen_height);
assert( success >= 0 );
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = state->screen_width;
dst_rect.height = state->screen_height;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = state->screen_width << 16;
src_rect.height = state->screen_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*/);
nativewindow.element = dispman_element;
nativewindow.width = state->screen_width;
nativewindow.height = state->screen_height;
vc_dispmanx_update_submit_sync( dispman_update );
state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, 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);
//DAVE - Set up screen ratio
glViewport(0, 0, (GLsizei)state->screen_width, (GLsizei)state->screen_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float ratio = (float)state->screen_width / (float)state->screen_height;
glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f);
}
// setfill sets the fill color
void setfill(float color[4]) {
VGPaint fillPaint = vgCreatePaint();
vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color);
vgSetPaint(fillPaint, VG_FILL_PATH);
vgDestroyPaint(fillPaint);
}
// setstroke sets the stroke color and width
void setstroke(float color[4], float width) {
VGPaint strokePaint = vgCreatePaint();
vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color);
vgSetPaint(strokePaint, VG_STROKE_PATH);
vgSetf(VG_STROKE_LINE_WIDTH, width);
vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
vgDestroyPaint(strokePaint);
}
// rect makes a rectangle at the specified location and dimensions, applying style
void Rect(float x, float y, float w, float h, float sw, float fill[4], float stroke[4]) {
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
vguRect(path, x, y, w, h);
setfill(fill);
setstroke(stroke, sw);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Line makes a line, applying style
void Line(float x1, float y1, float x2, float y2, float sw, float stroke[4]) {
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
vguLine(path, x1, y1, x2, y2);
setstroke(stroke, sw);
vgDrawPath(path, VG_STROKE_PATH);
vgDestroyPath(path);
}
// Roundrect makes an rounded rectangle at the specified location and dimensions, applying style
void Roundrect(float x, float y, float w, float h, float rw, float rh, float sw, float fill[4], float stroke[4]) {
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
vguRoundRect(path, x, y, w, h, rw, rh);
setfill(fill);
setstroke(stroke, sw);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Ellipse makes an ellipse at the specified location and dimensions, applying style
void Ellipse(float x, float y, float w, float h, float sw, float fill[4], float stroke[4]) {
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
vguEllipse(path, x, y, w, h);
setfill(fill);
setstroke(stroke, sw);
vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
vgDestroyPath(path);
}
// Start begins the picture, clearing a rectangluar region with a specified color
void Start(int width, int height, float fill[4]) {
vgSetfv(VG_CLEAR_COLOR, 4, fill);
vgClear(0, 0, width, height);
vgLoadIdentity();
}
// End checks for errors, and renders to the display
void End() {
assert(vgGetError() == VG_NO_ERROR);
eglSwapBuffers(state->display, state->surface);
assert(eglGetError() == EGL_SUCCESS);
}
// randcolor returns a fraction of 255
VGfloat randcolor() {
return (VGfloat)(rand() % 256) / 255.0;
}
// randf returns a floating point number bounded by n
VGfloat randf(n) {
return (VGfloat)(rand() % n);
}
// rshapes draws shapes (rect and ellipse) with random colors, strokes, and sizes.
void rshapes(int width, int height, int n) {
float rcolor[4], scolor[4], bgcolor[4] = {0,0,0,1};
scolor[3] = 1; // strokes are solid
srand ( time(NULL) );
Start(width, height, bgcolor);
int i;
for (i=0; i < n; i++) {
rcolor[0] = randcolor();
rcolor[1] = randcolor();
rcolor[2] = randcolor();
rcolor[3] = randcolor();
scolor[1] = randcolor();
scolor[2] = randcolor();
scolor[3] = randcolor();
if (i%2 == 0) {
Ellipse(randf(width), randf(height), randf(200), randf(100), randf(10), rcolor, scolor);
}
else {
Rect(randf(width), randf(height), randf(200), randf(100), randf(10), rcolor, scolor);
}
}
End();
}
// exit_func cleans up
static void exit_func(void) {
// clear screen
glClear( GL_COLOR_BUFFER_BIT );
eglSwapBuffers(state->display, state->surface);
// Release OpenGL resources
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 );
}
// main initializes the system and shows the picture,
// exit and clean up when you hit [RETURN].
int main (int argc, char **argv) {
int w, h, n;
bcm_host_init();
memset( state, 0, sizeof( *state ) ); // clear application state
init_ogl(state); // Start OGLES
w = state->screen_width;
h = state->screen_height;
n = 500;
if (argc > 1) {
n = atoi(argv[1]);
}
rshapes(w, h, n);
while (getchar() != '\n') {
;
}
exit_func();
return 0;
}
@ajstarks
Copy link
Author

Build on the Raspberry Pi with:

$ gcc -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -L/opt/vc/lib -lGLESv2 rshapes.c -o rshapes
$ ./rshapes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment