glview_cxx_example_01.cc
#include <Elementary.hh>
#include <Evas_GL.h>
#include <stdio.h>
typedef struct _GLData GLData;
struct _GLData
{
Evas_GL_API *glapi;
GLuint program;
GLuint vtx_shader;
GLuint fgmt_shader;
GLuint vbo;
int initialized : 1;
};
static float red = 1.0;
static GLuint
load_shader(GLData *gld, GLenum type, const char *shader_src )
{
Evas_GL_API *gl = gld->glapi;
GLuint shader;
GLint compiled;
shader = gl->glCreateShader(type);
if (shader==0)
return 0;
gl->glShaderSource(shader, 1, &shader_src, NULL);
gl->glCompileShader(shader);
gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
{
GLint info_len = 0;
gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
if (info_len > 1)
{
char* info_log = new char[sizeof(char) * info_len];
gl->glGetShaderInfoLog(shader, info_len, NULL, info_log);
printf("Error compiling shader:\n%s\n======\n%s\n======\n", info_log, shader_src );
delete [] info_log;
}
gl->glDeleteShader(shader);
return 0;
}
return shader;
}
static int
init_shaders(GLData *gld)
{
Evas_GL_API *gl = gld->glapi;
GLbyte vShaderStr[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
GLbyte fShaderStr[] =
"#ifdef GL_ES \n"
"precision mediump float; \n"
"#endif \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
GLint linked;
gld->vtx_shader = load_shader(gld, GL_VERTEX_SHADER, (const char*)vShaderStr);
gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, (const char*)fShaderStr);
gld->program = gl->glCreateProgram( );
if (gld->program==0)
return 0;
gl->glAttachShader(gld->program, gld->vtx_shader);
gl->glAttachShader(gld->program, gld->fgmt_shader);
gl->glBindAttribLocation(gld->program, 0, "vPosition");
gl->glLinkProgram(gld->program);
gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
if (!linked)
{
GLint info_len = 0;
gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
if (info_len > 1)
{
char* info_log = new char[sizeof(char) * info_len];
gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
printf("Error linking program:\n%s\n", info_log);
delete [] info_log;
}
gl->glDeleteProgram(gld->program);
return 0;
}
return 1;
}
static void
_init_gl(Evas_Object *obj)
{
GLData *gld = static_cast<GLData*>(evas_object_data_get(obj, "gld"));
assert(gld != 0);
::elm::glview glv(eo_ref(obj));
Evas_GL_API *gl = glv.gl_api_get();
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
if (!init_shaders(gld))
{
std::cout << "Error Initializing Shaders" << std::endl;
return;
}
gl->glGenBuffers(1, &gld->vbo);
gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
gl->glBufferData(GL_ARRAY_BUFFER, 3 * 3 * 4, vVertices, GL_STATIC_DRAW);
}
static void
_del_gl(Evas_Object *obj)
{
GLData *gld = static_cast<GLData*>(evas_object_data_get(obj, "gld"));
if (!gld)
{
std::cout << "Unable to get GLData. " << std::endl;
return;
}
::elm::glview glv(eo_ref(obj));
Evas_GL_API *gl = glv.gl_api_get();
gl->glDeleteShader(gld->vtx_shader);
gl->glDeleteShader(gld->fgmt_shader);
gl->glDeleteProgram(gld->program);
gl->glDeleteBuffers(1, &gld->vbo);
evas_object_data_del(obj, "..gld");
free(gld);
}
static void
_resize_gl(Evas_Object *obj)
{
int w, h;
::elm::glview glv(eo_ref(obj));
Evas_GL_API *gl = glv.gl_api_get();
glv.size_get(&w, &h);
gl->glViewport(0, 0, w, h);
}
static void
_draw_gl(Evas_Object *obj)
{
GLData *gld = static_cast<GLData*>(evas_object_data_get(obj, "gld"));
::elm::glview glv(eo_ref(obj));
Evas_GL_API *gl = glv.gl_api_get();
if (!gld) return;
int w, h;
glv.size_get(&w, &h);
gl->glViewport(0, 0, w, h);
gl->glClearColor(red,0.8,0.3,1);
gl->glClear(GL_COLOR_BUFFER_BIT);
gl->glEnable(GL_BLEND);
gl->glUseProgram(gld->program);
gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
gl->glEnableVertexAttribArray(0);
gl->glDrawArrays(GL_TRIANGLES, 0, 3);
gl->glFinish();
red -= 0.1;
if (red < 0.0) red = 1.0;
}
static Eina_Bool
_anim(void* data)
{
static_cast<elm::glview*>(data)->changed_set();
return EINA_TRUE;
}
EAPI_MAIN int
elm_main (int argc, char *argv[])
{
GLData *gld = NULL;
if (!(gld = static_cast<GLData*>(calloc(1, sizeof(GLData))))) return 1;
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
::elm::win win(elm_win_util_standard_add("glview simple", "GLView Simple"));
win.autohide_set(true);
::elm::box bx(efl::eo::parent = win);
bx.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
win.resize_object_add(bx);
bx.visible_set(true);
::elm::glview gl(efl::eo::parent = win,
gl.version_constructor(EVAS_GL_GLES_2_X));
gld->glapi = gl.gl_api_get();
gl.size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
gl.size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL);
gl.mode_set(static_cast<Elm_GLView_Mode>(gl_mode));
gl.resize_policy_set(ELM_GLVIEW_RESIZE_POLICY_RECREATE);
gl.render_policy_set(ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
gl.init_func_set(_init_gl);
gl.del_func_set(_del_gl);
gl.resize_func_set(_resize_gl);
gl.render_func_set(_draw_gl);
bx.pack_end(gl);
gl.visible_set(true);
gl.object::focus_set(true);
Ecore_Animator *ani = ecore_animator_add(_anim, &gl);
evas_object_data_set(gl._eo_ptr(), "ani", ani);
evas_object_data_set(gl._eo_ptr(), "gld", gld);
gl.object::callback_del_add(std::bind([&] () { ecore_animator_del(ani); }));
::elm::button bt(efl::eo::parent = win);
bt.text_set(nullptr, "OK");
bt.size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL);
bt.size_hint_weight_set(EVAS_HINT_EXPAND, 0.0);
bx.pack_end(bt);
bt.visible_set(true);
bt.callback_clicked_add(std::bind([] () { elm_exit(); }));
win.size_set(320, 480);
win.visible_set(true);
return 0;
}