bool EwkView::createGLSurface() { if (!m_isAccelerated) return true; static Evas_GL_Config evasGLConfig = { EVAS_GL_RGBA_8888, EVAS_GL_DEPTH_BIT_8, EVAS_GL_STENCIL_NONE, EVAS_GL_OPTIONS_NONE, EVAS_GL_MULTISAMPLE_NONE }; // Recreate to current size: Replaces if non-null, and frees existing surface after (OwnPtr). m_evasGLSurface = EvasGLSurface::create(m_evasGL.get(), &evasGLConfig, size()); if (!m_evasGLSurface) return false; Evas_Native_Surface nativeSurface; evas_gl_native_surface_get(m_evasGL.get(), m_evasGLSurface->surface(), &nativeSurface); evas_object_image_native_surface_set(smartData()->image, &nativeSurface); evas_gl_make_current(m_evasGL.get(), m_evasGLSurface->surface(), m_evasGLContext->context()); Evas_GL_API* gl = evas_gl_api_get(m_evasGL.get()); const WKPoint& boundsEnd = WKViewUserViewportToContents(wkView(), WKPointMake(size().width(), size().height())); gl->glViewport(0, 0, boundsEnd.x, boundsEnd.y); gl->glClearColor(1.0, 1.0, 1.0, 0); gl->glClear(GL_COLOR_BUFFER_BIT); return true; }
// Initialize the shader and program object 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; // Load the vertex/fragment shaders gld->vtx_shader = load_shader(gld, GL_VERTEX_SHADER, (const char*)vShaderStr); gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, (const char*)fShaderStr); // Create the program object gld->program = gl->glCreateProgram( ); if (0 == gld->program) 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 (1 < info_len) { char* info_log = malloc(sizeof(char) * info_len); gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log); _printf("Error linking program:\n%s\n", info_log); free(info_log); g_assert(FALSE); } gl->glDeleteProgram(gld->program); return 0; } return 1; }
static void _draw_gl(Evas_Object *obj) { Evas_GL_API *gl = elm_glview_gl_api_get(obj); GLData *gld = evas_object_data_get(obj, "gld"); if (!gld) return; render_gears(gld); gl->glFinish(); }
// resize callback gets called every time object is resized static void _resize_gl(Evas_Object *obj) { int w, h; GLData *gld = evas_object_data_get(obj, "gld"); Evas_GL_API *gl = gld->glapi; elm_glview_size_get(obj, &w, &h); // GL Viewport stuff. you can avoid doing this if viewport is all the // same as last frame if you want gl->glViewport(0, 0, w, h); }
bool EwkView::createGLSurface(const IntSize& viewSize) { if (!m_isHardwareAccelerated) return true; if (!m_evasGL) { Evas* evas = evas_object_evas_get(m_evasObject); m_evasGL = adoptPtr(evas_gl_new(evas)); if (!m_evasGL) { WARN("Failed to create Evas_GL, falling back to software mode."); m_isHardwareAccelerated = false; return false; } } if (!m_evasGLContext) { m_evasGLContext = EvasGLContext::create(m_evasGL.get()); if (!m_evasGLContext) { WARN("Failed to create GLContext."); return false; } } Ewk_View_Smart_Data* sd = smartData(); Evas_GL_Config evasGLConfig = { EVAS_GL_RGBA_8888, EVAS_GL_DEPTH_BIT_8, EVAS_GL_STENCIL_NONE, EVAS_GL_OPTIONS_NONE, EVAS_GL_MULTISAMPLE_NONE }; // Replaces if non-null, and frees existing surface after (OwnPtr). m_evasGLSurface = EvasGLSurface::create(m_evasGL.get(), &evasGLConfig, viewSize); if (!m_evasGLSurface) return false; Evas_Native_Surface nativeSurface; evas_gl_native_surface_get(m_evasGL.get(), m_evasGLSurface->surface(), &nativeSurface); evas_object_image_native_surface_set(sd->image, &nativeSurface); evas_gl_make_current(m_evasGL.get(), m_evasGLSurface->surface(), m_evasGLContext->context()); Evas_GL_API* gl = evas_gl_api_get(m_evasGL.get()); gl->glViewport(0, 0, viewSize.width() + sd->view.x, viewSize.height() + sd->view.y); gl->glClearColor(1.0, 1.0, 1.0, 0); gl->glClear(GL_COLOR_BUFFER_BIT); return true; }
//--------------------------------// static GLuint load_shader( GLData *gld, GLenum type, const char *shader_src ) { Evas_GL_API *gl = gld->glapi; GLuint shader; GLint compiled; // Create the shader object shader = gl->glCreateShader(type); if (shader==0) return 0; // Load/Compile shader source 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 = malloc(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 ); free(info_log); } gl->glDeleteShader(shader); return 0; } return shader; }
bool EwkView::createGLSurface() { if (!m_isAccelerated) return true; static Evas_GL_Config evasGLConfig = { EVAS_GL_RGBA_8888, EVAS_GL_DEPTH_BIT_8, EVAS_GL_STENCIL_NONE, EVAS_GL_OPTIONS_NONE, EVAS_GL_MULTISAMPLE_NONE, #if defined(EVAS_GL_API_VERSION) && EVAS_GL_API_VERSION >= 2 EVAS_GL_GLES_2_X #endif }; // Recreate to current size: Replaces if non-null, and frees existing surface after (OwnPtr). if (deviceSize().width() && deviceSize().height()) { Evas_GL_Surface* surface = nullptr; surface = evas_gl_surface_create(m_evasGL, &evasGLConfig, deviceSize().width(), deviceSize().height()); if (!surface) return false; m_evasGLSurface = std::make_unique<EvasGLSurface>(m_evasGL, surface); } if (!m_evasGLSurface) return false; Evas_Native_Surface nativeSurface; evas_gl_native_surface_get(m_evasGL, m_evasGLSurface->surface(), &nativeSurface); evas_object_image_native_surface_set(smartData()->image, &nativeSurface); evas_gl_make_current(m_evasGL, m_evasGLSurface->surface(), m_evasGLContext->context()); Evas_GL_API* gl = evas_gl_api_get(m_evasGL); WKPoint boundsEnd = WKViewUserViewportToScene(wkView(), WKPointMake(deviceSize().width(), deviceSize().height())); gl->glViewport(0, 0, boundsEnd.x, boundsEnd.y); gl->glClearColor(1.0, 1.0, 1.0, 0); gl->glClear(GL_COLOR_BUFFER_BIT); return true; }
// delete callback gets called when glview is deleted static void _del_gl(Evas_Object *obj) { GLData *gld = evas_object_data_get(obj, "gld"); if (!gld) { printf("Unable to get GLData. \n"); g_assert(FALSE); } Evas_GL_API *gl = gld->glapi; gl->glDeleteShader(gld->vtx_shader); gl->glDeleteShader(gld->fgmt_shader); gl->glDeleteProgram(gld->program); gl->glDeleteBuffers(1, &gld->vbo); evas_object_data_del((Evas_Object*)obj, "..gld"); free(gld); }
// intialize callback that gets called once for intialization static void _init_gl(Evas_Object *obj) { GLData *gld = evas_object_data_get(obj, "gld"); Evas_GL_API *gl = gld->glapi; GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; if (!init_shaders(gld)) { _printf("Error Initializing Shaders\n"); g_assert(FALSE); } gl->glGenBuffers(1, &gld->vbo); gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo); gl->glBufferData(GL_ARRAY_BUFFER, 3 * 3 * 4, vVertices, GL_STATIC_DRAW); }
/* new window size or exposure */ static void gears_reshape(GLData *gld, int width, int height) { Evas_GL_API *gl = gld->glapi; GLfloat ar, m[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 1.0 }; if (width < height) ar = width; else ar = height; m[0] = 0.1 * ar / width; m[5] = 0.1 * ar / height; memcpy(gld->proj, m, sizeof gld->proj); gl->glViewport(0, 0, (GLint) width, (GLint) height); }
static void gears_draw(GLData *gld) { Evas_GL_API *gl = gld->glapi; static const GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; static const GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; static const GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; GLfloat m[16]; gl->glClearColor(0.8, 0.8, 0.1, 0.5); gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); memcpy(m, gld->proj, sizeof m); rotate(m, 2 * M_PI * gld->view_rotx / 360.0, 1, 0, 0); rotate(m, 2 * M_PI * gld->view_roty / 360.0, 0, 1, 0); rotate(m, 2 * M_PI * gld->view_rotz / 360.0, 0, 0, 1); draw_gear(gld, gld->gear1, m, -3.0, -2.0, gld->angle, red); draw_gear(gld, gld->gear2, m, 3.1, -2.0, -2 * gld->angle - 9.0, green); draw_gear(gld, gld->gear3, m, -3.1, 4.2, -2 * gld->angle - 25.0, blue); }
static void draw_gear(GLData *gld, Gear *gear, GLfloat *m, GLfloat x, GLfloat y, GLfloat angle, const GLfloat *color) { Evas_GL_API *gl = gld->glapi; GLfloat tmp[16]; memcpy(tmp, m, sizeof tmp); translate(tmp, x, y, 0); rotate(tmp, 2 * M_PI * angle / 360.0, 0, 0, 1); gl->glUniformMatrix4fv(gld->proj_location, 1, GL_FALSE, tmp); gl->glUniform3fv(gld->light_location, 1, gld->light); gl->glUniform4fv(gld->color_location, 1, color); gl->glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), NULL); gl->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLfloat *) 0 + 3); gl->glEnableVertexAttribArray(0); gl->glEnableVertexAttribArray(1); gl->glDrawArrays(GL_TRIANGLE_STRIP, 0, gear->count); }
// draw callback is where all the main GL rendering happens static void _draw_gl(Evas_Object *obj) { Evas_GL_API *gl = elm_glview_gl_api_get(obj); GLData *gld = evas_object_data_get(obj, "gld"); if (!gld) return; int w, h; elm_glview_size_get(obj, &w, &h); gl->glViewport(0, 0, w, h); gl->glClearColor(red, 0.8, 0.3, 1); gl->glClear(GL_COLOR_BUFFER_BIT); // Draw a Triangle 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); // Optional - Flush the GL pipeline gl->glFinish(); red -= 0.1; if (0.0 > red) red = 1.0; }
/* Draw a gear wheel. You'll probably want to call this function when * building a display list since we do a lot of trig here. * * Input: inner_radius - radius of hole at center * outer_radius - radius at center of teeth * width - width of gear * teeth - number of teeth * tooth_depth - depth of tooth */ static Gear * make_gear(GLData *gld, GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth) { GLint i; GLfloat r0, r1, r2; GLfloat da; GLfloat *v; Gear *gear; double s[5], c[5]; GLfloat normal[3]; const int tris_per_tooth = 20; Evas_GL_API *gl = gld->glapi; gear = (Gear*)malloc(sizeof(Gear)); if (gear == NULL) return NULL; r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0; r2 = outer_radius + tooth_depth / 2.0; da = 2.0 * M_PI / teeth / 4.0; gear->vertices = calloc(teeth * tris_per_tooth * 3 * 6, sizeof *gear->vertices); s[4] = 0; c[4] = 1; v = gear->vertices; for (i = 0; i < teeth; i++) { s[0] = s[4]; c[0] = c[4]; s[1] = sin(i * 2.0 * M_PI / teeth + da); c[1] = cos(i * 2.0 * M_PI / teeth + da); s[2] = sin(i * 2.0 * M_PI / teeth + da * 2); c[2] = cos(i * 2.0 * M_PI / teeth + da * 2); s[3] = sin(i * 2.0 * M_PI / teeth + da * 3); c[3] = cos(i * 2.0 * M_PI / teeth + da * 3); s[4] = sin(i * 2.0 * M_PI / teeth + da * 4); c[4] = cos(i * 2.0 * M_PI / teeth + da * 4); normal[0] = 0.0; normal[1] = 0.0; normal[2] = 1.0; v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal); v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal); v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal); v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal); v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal); v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal); v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal); v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal); v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal); v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal); v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal); v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal); normal[0] = 0.0; normal[1] = 0.0; normal[2] = -1.0; v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal); v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal); v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal); v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal); v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal); v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal); v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal); v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal); v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal); v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal); v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal); v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal); v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal); v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal); v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal); v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal); v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal); v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal); v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal); v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal); } gear->count = (v - gear->vertices) / 6; gl->glGenBuffers(1, &gear->vbo); gl->glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); gl->glBufferData(GL_ARRAY_BUFFER, gear->count * 6 * 4, gear->vertices, GL_STATIC_DRAW); return gear; }
static void gears_init(GLData *gld) { Evas_GL_API *gl = gld->glapi; const char *p; char msg[512]; gl->glEnable(GL_CULL_FACE); gl->glEnable(GL_DEPTH_TEST); p = vertex_shader; gld->vtx_shader = gl->glCreateShader(GL_VERTEX_SHADER); gl->glShaderSource(gld->vtx_shader, 1, &p, NULL); gl->glCompileShader(gld->vtx_shader); gl->glGetShaderInfoLog(gld->vtx_shader, sizeof msg, NULL, msg); printf("vertex shader info: %s\n", msg); p = fragment_shader; gld->fgmt_shader = gl->glCreateShader(GL_FRAGMENT_SHADER); gl->glShaderSource(gld->fgmt_shader, 1, &p, NULL); gl->glCompileShader(gld->fgmt_shader); gl->glGetShaderInfoLog(gld->fgmt_shader, sizeof msg, NULL, msg); printf("fragment shader info: %s\n", msg); gld->program = gl->glCreateProgram(); gl->glAttachShader(gld->program, gld->vtx_shader); gl->glAttachShader(gld->program, gld->fgmt_shader); gl->glBindAttribLocation(gld->program, 0, "position"); gl->glBindAttribLocation(gld->program, 1, "normal"); gl->glLinkProgram(gld->program); gl->glGetProgramInfoLog(gld->program, sizeof msg, NULL, msg); printf("info: %s\n", msg); gl->glUseProgram(gld->program); gld->proj_location = gl->glGetUniformLocation(gld->program, "proj"); gld->light_location = gl->glGetUniformLocation(gld->program, "light"); gld->color_location = gl->glGetUniformLocation(gld->program, "color"); /* make the gears */ gld->gear1 = make_gear(gld, 1.0, 4.0, 1.0, 20, 0.7); gld->gear2 = make_gear(gld, 0.5, 2.0, 2.0, 10, 0.7); gld->gear3 = make_gear(gld, 1.3, 2.0, 0.5, 10, 0.7); }