Skip to content

Instantly share code, notes, and snippets.

@ngocdaothanh
Created January 27, 2013 13:15
Show Gist options
  • Save ngocdaothanh/4648313 to your computer and use it in GitHub Desktop.
Save ngocdaothanh/4648313 to your computer and use it in GitHub Desktop.
// From http://code.google.com/p/android-native-egl-example/
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include <android/native_window.h> // requires ndk r5 or newer
#include <EGL/egl.h> // requires ndk r5 or newer
#include <GLES2/gl2.h>
#include "logger.h"
#include "renderer.h"
#include <cairo.h>
#include <cairo-gl.h>
#include <EGL/egl.h>
#include "gl.h"
#define LOG_TAG "EglSample"
cairo_device_t *cairoEGLDevice;
cairo_surface_t *cairoSurface;
cairo_t *cr;
Renderer::Renderer()
{
LOG_INFO("Renderer instance created");
pthread_mutex_init(&_mutex, 0);
_display = 0;
_surface = 0;
_context = 0;
_angle = 0;
return;
}
Renderer::~Renderer()
{
LOG_INFO("Renderer instance destroyed");
pthread_mutex_destroy(&_mutex);
return;
}
void Renderer::start()
{
LOG_INFO("Creating renderer thread");
pthread_create(&_threadId, 0, threadStartCallback, this);
return;
}
void Renderer::stop()
{
LOG_INFO("Stopping renderer thread");
// send message to render thread to stop rendering
pthread_mutex_lock(&_mutex);
_msg = MSG_RENDER_LOOP_EXIT;
pthread_mutex_unlock(&_mutex);
pthread_join(_threadId, 0);
LOG_INFO("Renderer thread stopped");
return;
}
void Renderer::setWindow(ANativeWindow *window)
{
// notify render thread that window has changed
pthread_mutex_lock(&_mutex);
_msg = MSG_WINDOW_SET;
_window = window;
pthread_mutex_unlock(&_mutex);
return;
}
void Renderer::renderLoop()
{
bool renderingEnabled = true;
LOG_INFO("renderLoop()");
while (renderingEnabled) {
pthread_mutex_lock(&_mutex);
// process incoming messages
switch (_msg) {
case MSG_WINDOW_SET:
initialize();
break;
case MSG_RENDER_LOOP_EXIT:
renderingEnabled = false;
destroy();
break;
default:
break;
}
_msg = MSG_NONE;
if (_display) {
drawFrame();
cairo_gl_surface_swapbuffers(cairoSurface);
/*
if (!eglSwapBuffers(_display, _surface)) {
LOG_ERROR("eglSwapBuffers() returned error %d", eglGetError());
}
*/
}
pthread_mutex_unlock(&_mutex);
}
LOG_INFO("Render loop exits");
return;
}
bool Renderer::initialize()
{
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
const EGLint eglCreateContextattribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLDisplay display;
EGLConfig config;
EGLint numConfigs;
EGLint format;
EGLSurface surface;
EGLContext context;
EGLint width;
EGLint height;
if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
LOG_ERROR("eglGetDisplay() returned error %d", eglGetError());
return false;
}
if (!eglInitialize(display, 0, 0)) {
LOG_ERROR("eglInitialize() returned error %d", eglGetError());
return false;
}
if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) {
LOG_ERROR("eglChooseConfig() returned error %d", eglGetError());
destroy();
return false;
}
if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
LOG_ERROR("eglGetConfigAttrib() returned error %d", eglGetError());
destroy();
return false;
}
ANativeWindow_setBuffersGeometry(_window, 0, 0, format);
if (!(surface = eglCreateWindowSurface(display, config, _window, 0))) {
LOG_ERROR("eglCreateWindowSurface() returned error %d", eglGetError());
destroy();
return false;
}
if (!(context = eglCreateContext(display, config, EGL_NO_CONTEXT, eglCreateContextattribs))) {
LOG_ERROR("eglCreateContext() returned error %d", eglGetError());
destroy();
return false;
}
if (!eglMakeCurrent(display, surface, surface, context)) {
LOG_ERROR("eglMakeCurrent() returned error %d", eglGetError());
destroy();
return false;
}
if (!eglQuerySurface(display, surface, EGL_WIDTH, &width) ||
!eglQuerySurface(display, surface, EGL_HEIGHT, &height)) {
LOG_ERROR("eglQuerySurface() returned error %d", eglGetError());
destroy();
return false;
}
GL::setupGraphics(width, height);
glClearColor(0.5, 0.5, 0.5, 0.5);
cairoEGLDevice = cairo_egl_device_create(display, context);
cairoSurface = cairo_gl_surface_create(cairoEGLDevice, CAIRO_CONTENT_COLOR_ALPHA, width, height);
//cairoSurface = cairo_gl_surface_create_for_egl(cairoEGLDevice, surface, width, height);
cr = cairo_create(cairoSurface);
eglMakeCurrent(display, surface, surface, context);
_display = display;
_surface = surface;
_context = context;
_width = width;
_height = height;
return true;
}
void Renderer::destroy() {
LOG_INFO("Destroying context");
eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(_display, _context);
eglDestroySurface(_display, _surface);
eglTerminate(_display);
_display = EGL_NO_DISPLAY;
_surface = EGL_NO_SURFACE;
_context = EGL_NO_CONTEXT;
_width = 0;
_height = 0;
return;
}
#include <math.h>
void Renderer::drawFrame()
{
static int tick = 0;
tick++;
glClear(GL_COLOR_BUFFER_BIT);
cairo_scale(cr, 720, 1134);
/* Draw the big X */
double position = (tick%30)*(1.0/30);
cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.7);
cairo_move_to (cr, 0.1, position);
cairo_line_to (cr, 0.9, 1.0-position);
cairo_move_to (cr, 0.9, position);
cairo_line_to (cr, 0.1, 1.0-position);
cairo_set_line_width (cr, 0.1);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_stroke (cr);
/* Draw three color squares */
cairo_rectangle (cr, 0, 0,0.5, 0.5);
cairo_set_source_rgba (cr, 1, 0, 0, 0.50);
cairo_fill (cr);
cairo_rectangle (cr, 0, 0.5, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 1, 0, 0.50);
cairo_fill (cr);
cairo_rectangle (cr, 0.5, 0, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 0, 1, 0.50);
cairo_fill (cr);
/* Draw a more complicated path */
cairo_set_line_width (cr, 0.04);
cairo_scale(cr, 0.5, 0.5);
cairo_translate(cr, 0.5, 1.0);
cairo_set_source_rgba (cr, 1.0, 0.2, 0.0, 0.5);
cairo_move_to (cr, 0.25, 0.25);
cairo_line_to (cr, 0.5, 0.375);
cairo_rel_line_to (cr, 0.25, -0.125);
cairo_arc (cr, 0.5, 0.5, 0.25 * sqrt(2), -0.25 * M_PI, 0.25 * M_PI);
cairo_rel_curve_to (cr, -0.25, -0.125, -0.25, 0.125, -0.5, 0);
cairo_close_path (cr);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
cairo_stroke (cr);
}
void* Renderer::threadStartCallback(void *myself)
{
Renderer *renderer = (Renderer*)myself;
renderer->renderLoop();
pthread_exit(0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment