From bb23c72a3ef3e460c8b88230354af65e78240d49 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Fri, 2 May 2014 19:52:58 +1000 Subject: Major cleanup of extantz, part one. --- src/extantz/extantz.c | 421 +++++++++++++++++++------------------------------- 1 file changed, 156 insertions(+), 265 deletions(-) (limited to 'src/extantz/extantz.c') diff --git a/src/extantz/extantz.c b/src/extantz/extantz.c index 31264fd..28df70f 100644 --- a/src/extantz/extantz.c +++ b/src/extantz/extantz.c @@ -6,7 +6,6 @@ globals ourGlobals; static void gldata_init(GLData *gld) { - gld->useEGL = USE_EGL; gld->useIrr = USE_IRR; gld->view_rotx = -20.0; @@ -72,126 +71,33 @@ static void _resize_gl(Evas_Object *obj) _resize(gld); } -static void on_pixels(void *data, Evas_Object *obj) -{ - GLData *gld = data; - Evas_GL_API *gl = gld->glApi; - - // get the image size in case it changed with evas_object_image_size_set() - if (gld->r1) - { - Evas_Coord w, h; - - // Poor mans resize check. coz Elm wont do it easily. - evas_object_image_size_get(gld->r1, &w, &h); - if ((gld->img_w != w) || (gld->img_h != h)) - { - // No idea where this crap came from. - //float new_w = ((float) gld->scr_w / ((float) gld->scr_w * (float) w)); - //float new_h = ((float) gld->scr_h / ((float) gld->scr_h * (float) h)); - - //gld->sfc_w = new_w; - //gld->sfc_h = new_h; - //evas_object_image_fill_set(gld->r1, 0, 0, gld->sfc_w, gld->sfc_h); - gld->img_w = w; - gld->img_h = h; - gld->resized = 1; - } - } - - if (gld->useEGL) - { - // Yes, we DO need to do our own make current, coz aparently the Irrlicht one is useless. - // Hopefully Elm_GL has done this for us by now. - // Evas_GL needs it to. - if (gld->ctx) - evas_gl_make_current(gld->evasGl, gld->sfc, gld->ctx); - } - - if (!gld->doneIrr) - gld->doneIrr = startIrr(gld); // Needs to be after gld->win is shown, and needs to be done in the render thread. -#if DO_GEARS - if (!gld->gearsInited) - gears_init(gld); -#endif - - if (gld->resized) - _resize(gld); - - drawIrr_start(gld); - -#if DO_GEARS - if (gld->useEGL) - drawGears(gld); -#endif - - drawIrr_end(gld); - -#if USE_IR -#else - // This might get done deep within drawIrr_end, but only if we are using Irrlicht. - - // Optional - Flush the GL pipeline - gl->glFlush(); -// gl->glFinish(); -#endif - - gld->resized = 0; -} - -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; - - on_pixels(gld, obj); -} - // Callback from Evas, also used as the general callback for deleting the GL stuff. static void _clean_gl(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { GLData *gld = data; - Evas_GL_API *gl = gld->glApi; ecore_animator_del(gld->animator); - if (gld->useEGL) - { - // Do a make_current before deleting all the GL stuff. - evas_gl_make_current(gld->evasGl, gld->sfc, gld->ctx); + // Do a make_current before deleting all the GL stuff. +// evas_gl_make_current(NULL, NULL, NULL); - } + // TODO - Since this is created on the render thread, better hope this is being deleted on the render thread. + finishIrr(gld); + +#if DO_GEARS + Evas_GL_API *gl = gld->glApi; gl->glDeleteShader(gld->vtx_shader); gl->glDeleteShader(gld->fgmt_shader); gl->glDeleteProgram(gld->program); - if (gld->evasGl) - { - // Irrlicht wants to destroy the context and surface, so only do this if Irrlicht wont. - if (!gld->doneIrr) - { - evas_gl_surface_destroy(gld->evasGl, gld->sfc); - evas_gl_context_destroy(gld->evasGl, gld->ctx); - } - // TODO - hope this is OK, considering the context and surface might get dealt with by Irrlicht. - // Might be better to teach Irrlicht to not destroy shit it did not create. - evas_gl_config_free(gld->cfg); - evas_gl_free(gld->evasGl); - } + gl->glDeleteBuffers(1, &gld->gear1->vbo); + gl->glDeleteBuffers(1, &gld->gear2->vbo); + gl->glDeleteBuffers(1, &gld->gear3->vbo); - // TODO - Since this is created on the render thread, better hope this is being deleted on the render thread. - finishIrr(gld); - -#if DO_GEARS - gl->glDeleteBuffers(1, &gld->gear1->vbo); - gl->glDeleteBuffers(1, &gld->gear2->vbo); - gl->glDeleteBuffers(1, &gld->gear3->vbo); - - free_gear(gld->gear1); - free_gear(gld->gear2); - free_gear(gld->gear3); + free_gear(gld->gear1); + free_gear(gld->gear2); + free_gear(gld->gear3); #endif } @@ -218,31 +124,74 @@ static void _on_done(void *data, Evas_Object *obj EINA_UNUSED, void *event_info elm_exit(); } -// Callback from the animator. -static Eina_Bool doFrame(void *data) +static void _draw_gl(Evas_Object *obj) { - GLData *gld = data; + globals *ourGlobals = evas_object_data_get(obj, "glob"); + GLData *gld = &ourGlobals->gld; + + if (!gld->doneIrr) gld->doneIrr = startIrr(gld); // Needs to be after gld->win is shown, and needs to be done in the render thread. +#if DO_GEARS + if (!gld->gearsInited) gears_init(gld); +#endif + +// if (gld->resized) _resize(gld); + + drawIrr_start(gld); + +#if DO_GEARS + drawGears(gld); +#endif + + _animate_scene(ourGlobals->scene); + + drawIrr_end(gld); + +#if USE_IRR +#else + // This might get done deep within drawIrr_end, but only if we are using Irrlicht. + + // Optional - Flush the GL pipeline +// gl->glFlush(); +// gl->glFinish(); +#endif - // Mark the pixels as dirty, so they get rerendered each frame, then Irrlicht can draw it's stuff each frame. - // This causes on_pixel to be triggered by Evas_GL, and _draw_gl for Elm_glview. - if (gld->r1) - evas_object_image_pixels_dirty_set(gld->r1, EINA_TRUE); - if (gld->elmGl) - elm_glview_changed_set(gld->elmGl); + gld->resized = 0; +} - // If not using Evas_GL, we need to call on_pixel() manually. - if (!gld->useEGL) - on_pixels(gld, gld->r1); +static void on_pixels(void *data, Evas_Object *obj) +{ + _draw_gl(obj); +} - return EINA_TRUE; // Keep calling us. +// Callback from the animator. +static Eina_Bool doFrame(void *data) +{ + globals *ourGlobals = data; + GLData *gld = &ourGlobals->gld; + + // Mark the pixels as dirty, so they get rerendered each frame, then Irrlicht can draw it's stuff each frame. + // This causes on_pixel to be triggered by Evas_3D, or _draw_gl for Elm_glview. + // Either way, _draw_gl gets called eventully. + if (gld->elmGl) + elm_glview_changed_set(gld->elmGl); + else if (ourGlobals->scene->image) + { +// evas_object_image_pixels_dirty_set(elm_image_object_get(ourGlobals->scene->image), EINA_TRUE); + _draw_gl(elm_image_object_get(ourGlobals->scene->image)); + } + + return EINA_TRUE; // Keep calling us. } -static void init_evas_gl(GLData *gld) +static void init_evas_gl(globals *ourGlobals) { - if (!gld->useEGL) - return; + GLData *gld = &ourGlobals->gld; + + gld->sfc_w = gld->win_w; + gld->sfc_h = gld->win_h; - gld->sfc_w = gld->win_w; + if (USE_IRR || DO_GEARS) + { gld->sfc_h = gld->win_h; // Get the Evas / canvas from the elm window (that the Evas_Object "lives on"), which is itself an Evas_Object created by Elm, so not sure if it was created internally with Ecore_Evas. @@ -251,7 +200,6 @@ static void init_evas_gl(GLData *gld) // Get the Ecore_Evas that wraps an Evas. gld->ee = ecore_evas_ecore_evas_get(gld->canvas); // Only use this on Evas that was created with Ecore_Evas. -#if USE_ELM_GL // Add a GLView gld->elmGl = elm_glview_add(gld->win); evas_object_size_hint_align_set(gld->elmGl, EVAS_HINT_FILL, EVAS_HINT_FILL); @@ -272,82 +220,19 @@ static void init_evas_gl(GLData *gld) //elm_win_resize_object_add(gld->win, gld->elmGl); gld->glApi = elm_glview_gl_api_get(gld->elmGl); evas_object_data_set(gld->elmGl, "gld", gld); + evas_object_data_set(gld->elmGl, "glob", ourGlobals); evas_object_show(gld->elmGl); elm_box_pack_end(gld->bx, gld->elmGl); -#else - // get the evas gl handle for doing gl things - gld->evasGl = evas_gl_new(gld->canvas); - gld->glApi = evas_gl_api_get(gld->evasGl); - - // Set a surface config - gld->cfg = evas_gl_config_new(); - gld->cfg->color_format = EVAS_GL_RGBA_8888; - gld->cfg->depth_bits = EVAS_GL_DEPTH_BIT_32; - gld->cfg->stencil_bits = EVAS_GL_STENCIL_NONE; - gld->cfg->options_bits = EVAS_GL_OPTIONS_DIRECT; - - // create a surface and context - gld->sfc = evas_gl_surface_create(gld->evasGl, gld->cfg, gld->sfc_w, gld->sfc_h); - gld->ctx = evas_gl_context_create(gld->evasGl, NULL); // The second NULL is for sharing contexts I think, which might be what we want to do with Irrlicht. It's not documented. - - // Set up the image object, a filled one by default. - gld->r1 = evas_object_image_filled_add(gld->canvas); - - // attach important data we need to the object using key names. This just - // avoids some global variables and means we can do nice cleanup. You can - // avoid this if you are lazy - // Not actually needed, with evas we can pass data pointers to stuff. - //evas_object_data_set(gld->r1, "gld", gld); - - // when the object is deleted - call the on_del callback. like the above, - // this is just being clean - evas_object_event_callback_add(gld->r1, EVAS_CALLBACK_DEL, _clean_gl, gld); - - // set up an actual pixel size for the buffer data. it may be different - // to the output size. any windowing system has something like this, just - // evas has 2 sizes, a pixel size and the output object size - evas_object_image_size_set(gld->r1, gld->sfc_w, gld->sfc_h); - // Not actualy needed, as we create the image already filled. - //evas_object_image_fill_set(gld->r1, 0, 0, gld->sfc_w, gld->sfc_h); - - // These two are not in the original example, but I get black r1 when I leave them out. - evas_object_size_hint_align_set(gld->r1, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(gld->r1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - - // set up the native surface info to use the context and surface created - // above - evas_gl_native_surface_get(gld->evasGl, gld->sfc, &(gld->ns)); - evas_object_image_native_surface_set(gld->r1, &(gld->ns)); - evas_object_image_pixels_get_callback_set(gld->r1, on_pixels, gld); - - // move the image object somewhere, resize it and show it. any windowing - // system would need this kind of thing - place a child "window" - // Hmm, no need to resize it anyway, it's sized above. - evas_object_move(gld->r1, 0, 0); - //evas_object_resize(gld->r1, gld->sfc_w, gld->sfc_h); - elm_win_resize_object_add(gld->win, gld->r1); - evas_object_show(gld->r1); - elm_box_pack_end(gld->bx, gld->r1); - -// evas_object_event_callback_add(gld->r1, EVAS_CALLBACK_MOUSE_DOWN, _cb_mouse_down_GL, gld); -// evas_object_event_callback_add(gld->r1, EVAS_CALLBACK_KEY_DOWN, _on_camera_input_down, gld); -// evas_object_event_callback_add(gld->r1, EVAS_CALLBACK_KEY_UP, _on_camera_input_up, gld); -#endif + } - // NOTE: if you delete r1, this animator will keep running trying to access - // r1 so you'd better delete this animator with ecore_animator_del() or - // structure how you do animation differently. you can also attach it like - // evasGl, sfc, etc. etc. if this animator is specific to this object - // only and delete it in the del handler for the obj. - // - // TODO - apparently the proper way to deal with the new async rendering is to have this animator do the dirty thing, and call the Irrlicht rendering stuff in the on_pixel call set above. - // That still leaves the problem of the Irrlicht setup being in the main thread. Which also should be done in on_pixel, as that's done in the correct thread. - - // Jiggling this seems to produce a trade off between flickering and frame rate. Nothing else changed the flickering. - ecore_animator_frametime_set(0.04); // Default is 1/30, or 0.033333 - gld->animator = ecore_animator_add(doFrame, gld); // This animator will be called every frame tick, which defaults to 1/30 seconds. - - return; + // TODO - apparently the proper way to deal with the new async rendering is to have this animator do the dirty thing, and call the Irrlicht rendering stuff in the _draw_gl call set above. + // That still leaves the problem of the Irrlicht setup being in the main thread. Which also should be done in on_pixel, as that's done in the correct thread. + + // Jiggling this seems to produce a trade off between flickering and frame rate. Nothing else changed the flickering. + ecore_animator_frametime_set(0.04); // Default is 1/30, or 0.033333 + gld->animator = ecore_animator_add(doFrame, ourGlobals); // This animator will be called every frame tick, which defaults to 1/30 seconds. + + return; } @@ -358,7 +243,6 @@ static Evas_Object *_toolbar_menu_add(Evas_Object *win, Evas_Object *tb, char *l { Evas_Object *menu= NULL; Elm_Object_Item *tb_it; -//, *menu_it; tb_it = elm_toolbar_item_append(tb, NULL, label, NULL, NULL); elm_toolbar_item_menu_set(tb_it, EINA_TRUE); @@ -370,11 +254,64 @@ static Evas_Object *_toolbar_menu_add(Evas_Object *win, Evas_Object *tb, char *l return menu; } +static void makeMainMenu(GLData *gld) +{ + Evas_Object *menu, *tb; + Elm_Object_Item *tb_it; + + // A toolbar thingy. + tb = eo_add(ELM_OBJ_TOOLBAR_CLASS, gld->win); + eo_do(tb, + evas_obj_size_hint_weight_set(EVAS_HINT_EXPAND, 0.0), + evas_obj_size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL), + elm_obj_toolbar_shrink_mode_set(ELM_TOOLBAR_SHRINK_SCROLL), + evas_obj_size_set(gld->win_w, 25), + evas_obj_position_set(0, 0), + elm_obj_toolbar_align_set(0.0) + ); + + // Menus. + menu = _toolbar_menu_add(gld->win, tb, "file"); + elm_menu_item_add(menu, NULL, NULL, "quit", _on_done, gld); + + menu = _toolbar_menu_add(gld->win, tb, "edit"); + elm_menu_item_add(menu, NULL, NULL, "preferences", NULL, NULL); + + menu = _toolbar_menu_add(gld->win, tb, "view"); + menu = _toolbar_menu_add(gld->win, tb, "world"); + menu = _toolbar_menu_add(gld->win, tb, "tools"); + + menu = _toolbar_menu_add(gld->win, tb, "help"); + elm_menu_item_add(menu, NULL, NULL, "grid help", NULL, NULL); + elm_menu_item_separator_add(menu, NULL); + elm_menu_item_add(menu, NULL, NULL, "extantz blogs", NULL, NULL); + elm_menu_item_add(menu, NULL, NULL, "extantz forum", NULL, NULL); + elm_menu_item_separator_add(menu, NULL); + elm_menu_item_add(menu, NULL, NULL, "about extantz", NULL, NULL); + + menu = _toolbar_menu_add(gld->win, tb, "advanced"); + elm_menu_item_add(menu, NULL, NULL, "debug settings", NULL, NULL); + + menu = _toolbar_menu_add(gld->win, tb, "god"); + + // Other stuff in the toolbar. + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_toolbar_item_separator_set(tb_it, EINA_TRUE); + tb_it = elm_toolbar_item_append(tb, NULL, "restriction icons", NULL, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_toolbar_item_separator_set(tb_it, EINA_TRUE); + tb_it = elm_toolbar_item_append(tb, NULL, "hop://localhost/Anarchadia 152, 155, 51 - Lost plot (Adult)", NULL, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_toolbar_item_separator_set(tb_it, EINA_TRUE); + tb_it = elm_toolbar_item_append(tb, NULL, "date time:o'clock", NULL, NULL); + + evas_object_show(tb); + eo_unref(tb); +} EAPI_MAIN int elm_main(int argc, char **argv) { - Evas_Object *obj, *menu, *tb; - Elm_Object_Item *tb_it; + Evas_Object *obj; EPhysics_World *world; GLData *gld = NULL; char buf[PATH_MAX]; @@ -398,16 +335,15 @@ EAPI_MAIN int elm_main(int argc, char **argv) elm_config_finger_size_set(0); elm_config_scale_set(1.0); - // alloc a data struct to hold our relevant gl info in - if (!(gld = calloc(1, sizeof(GLData)))) return 1; + gld = &ourGlobals.gld; gldata_init(gld); // Set the engine to opengl_x11, then open our window. - if (gld->useEGL) - elm_config_preferred_engine_set("opengl_x11"); - gld->win = elm_win_add(NULL, "extantz", ELM_WIN_BASIC); + elm_config_preferred_engine_set("opengl_x11"); gld->win = elm_win_util_standard_add("extantz", "extantz virtual world viewer"); ourGlobals.win = gld->win; + // Get the Evas / canvas from the elm window (that the Evas_Object "lives on"), which is itself an Evas_Object created by Elm, so not sure if it was created internally with Ecore_Evas. + ourGlobals.evas = evas_object_evas_get(gld->win); // Set preferred engine back to default from config elm_config_preferred_engine_set(NULL); @@ -425,9 +361,6 @@ EAPI_MAIN int elm_main(int argc, char **argv) gld->win_w = gld->scr_w / 2; gld->win_h = gld->scr_h - 30; - // Get the Evas / canvas from the elm window (that the Evas_Object "lives on"), which is itself an Evas_Object created by Elm, so not sure if it was created internally with Ecore_Evas. - ourGlobals.evas = evas_object_evas_get(gld->win); - // Add a background image object. obj = eo_add(ELM_OBJ_IMAGE_CLASS, gld->win); snprintf(buf, sizeof(buf), "%s/sky_03.jpg", elm_app_data_dir_get()); @@ -440,15 +373,16 @@ EAPI_MAIN int elm_main(int argc, char **argv) elm_win_resize_object_add(gld->win, obj); eo_unref(obj); - Evas_3D_Demo_add(&ourGlobals); - gld->bx = elm_box_add(gld->win); - evas_object_size_hint_weight_set(gld->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(gld->bx, EVAS_HINT_FILL, EVAS_HINT_FILL); + gld->bx = eo_add(ELM_OBJ_BOX_CLASS, gld->win); + eo_do(gld->bx, + evas_obj_size_hint_weight_set(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND), + evas_obj_size_hint_align_set(EVAS_HINT_FILL, EVAS_HINT_FILL), + evas_obj_visibility_set(EINA_TRUE) + ); elm_win_resize_object_add(gld->win, gld->bx); - evas_object_show(gld->bx); - overlay_add(gld); +// overlay_add(gld); woMan_add(gld); // TODO - This is what causes it to hang after quitting. Fix it. // chat_add(gld); @@ -456,60 +390,16 @@ EAPI_MAIN int elm_main(int argc, char **argv) // Gotta do this after adding the windows, otherwise the menu renders under the window. // This sucks, gotta redefine this menu each time we create a new window? // Also, GL focus gets lost when any menu is used. sigh - - // A toolbar thingy. - tb = elm_toolbar_add(gld->win); - evas_object_size_hint_weight_set(tb, EVAS_HINT_EXPAND, 0.0); - evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_toolbar_shrink_mode_set(tb, ELM_TOOLBAR_SHRINK_SCROLL); - elm_toolbar_align_set(tb, 0.0); - - // Menus. - menu = _toolbar_menu_add(gld->win, tb, "file"); - elm_menu_item_add(menu, NULL, NULL, "quit", _on_done, gld); - - menu = _toolbar_menu_add(gld->win, tb, "edit"); - elm_menu_item_add(menu, NULL, NULL, "preferences", NULL, NULL); - - menu = _toolbar_menu_add(gld->win, tb, "view"); - menu = _toolbar_menu_add(gld->win, tb, "world"); - menu = _toolbar_menu_add(gld->win, tb, "tools"); - - menu = _toolbar_menu_add(gld->win, tb, "help"); - elm_menu_item_add(menu, NULL, NULL, "grid help", NULL, NULL); - elm_menu_item_separator_add(menu, NULL); - elm_menu_item_add(menu, NULL, NULL, "extantz blogs", NULL, NULL); - elm_menu_item_add(menu, NULL, NULL, "extantz forum", NULL, NULL); - elm_menu_item_separator_add(menu, NULL); - elm_menu_item_add(menu, NULL, NULL, "about extantz", NULL, NULL); - - menu = _toolbar_menu_add(gld->win, tb, "advanced"); - elm_menu_item_add(menu, NULL, NULL, "debug settings", NULL, NULL); - - menu = _toolbar_menu_add(gld->win, tb, "god"); - - // Other stuff in the toolbar. - tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); - elm_toolbar_item_separator_set(tb_it, EINA_TRUE); - tb_it = elm_toolbar_item_append(tb, NULL, "restriction icons", NULL, NULL); - tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); - elm_toolbar_item_separator_set(tb_it, EINA_TRUE); - tb_it = elm_toolbar_item_append(tb, NULL, "hop://localhost/Anarchadia 152, 155, 51 - Lost plot (Adult)", NULL, NULL); - tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); - elm_toolbar_item_separator_set(tb_it, EINA_TRUE); - tb_it = elm_toolbar_item_append(tb, NULL, "date time:o'clock", NULL, NULL); - - // The toolbar needs to be packed into the box AFTER the menus are added. - evas_object_show(tb); - elm_box_pack_start(gld->bx, tb); + makeMainMenu(gld); // This does elm_box_pack_end(), so needs to be after the others. - init_evas_gl(gld); + init_evas_gl(&ourGlobals); - evas_object_show(gld->bx); + Evas_3D_Demo_add(&ourGlobals); + evas_object_data_set(elm_image_object_get(ourGlobals.scene->image), "glob", &ourGlobals); + evas_object_image_pixels_get_callback_set(elm_image_object_get(ourGlobals.scene->image), on_pixels, &ourGlobals); #if USE_PHYSICS - // ePhysics stuff. world = ephysicsAdd(gld); #endif @@ -528,9 +418,10 @@ EAPI_MAIN int elm_main(int argc, char **argv) if (gld->win) { + eo_unref(gld->bx); + Evas_3D_Demo_fini(); evas_object_del(gld->win); } - free(gld); if (ourGlobals.logDom >= 0) { -- cgit v1.1