[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [E-devel] Putting GL-textures into Etk, Evas, bla bla... How to choke a horse with words.



Here is a fixed version of the test code. It fixes the back-face
culling and some glPush/Pop*() bugs.

Simon


On Sun, 12 Nov 2006 18:21:09 +0100,
Simon TRENY <simon.treny@free.fr> wrote :

> Hi Rene,
> 
> The main problem we have here is that what you'd like to do is
> definitely engine-specific whereas Evas tends to abstract totally the
> engine layer. Anyway, with some Evas engines it should be quite easy
> to use OpenGL to render 3D stuff. Here is how to do it with the
> GL-X11 engine of Evas (which is obviously the most appropriate engine
> to do that since it already provides the GL context).
> 
> So, with the GL-X11 engine of Evas, all you have to do basically is to
> call all your OpenGL functions before glXSwapBuffers() gets called.
> glXSwapBuffers() is called by the output_flush() method of the GL-X11
> engine, which is called by evas_render_updates_internal(). So the
> problem is that we need to be somehow notified before
> evas_render_updates_internal() calls the output_flush() method, and,
> for now, there is no way to do that. I have written a small patch for
> Evas to add a callback called each time before output_flush() is
> called. The function to set this callback is
> evas_flush_callback_set(). The Evas patch is joined with this email
> (this patch should not be applied to the CVS repository of Evas, it's
> a quick'n'dirty hack!!).
> 
> Now, all you have to do is to make the calls to the OpenGL functions
> in the "flush-callback". I have attached a a small code that shows
> how to do it. It's totally dirty and hacky but it works quite well :)
> There is just a small problem with the Zbuffer of with the backbface
> culling I guess (the cube looks weird...), but it shouldn't be hard
> to fix. To compile this code, you have to apply the patch to Evas,
> and to compile it with:
> gcc -o evas_gl_proto evas_gl_proto.c `ecore-config --cflags --libs`
> -lGL -lGLU -Wall
> 
> 
> Note that the GL engine of Evas has some serious problems though. Here
> is a list of the know problems written by raster some times ago:
> > 1. a font with glyphs > 256x256 pixels will just break.
> > 2. images that are bigger than max texture size simply won't show
> > (need to build a mesh)
> > 3. cards that don't support rectangular textures will end up with
> > nasty scaling results when scaling "stretched" or "squashed" mostly
> > in 1 dimension (mipmap issues basically when used for 2d)
> > 4. scaling down even with smooth scaling is ugly (need to use
> > anisotropic filtering  if possible)
> > 5. doesn't support destination alpha (easy-ish to fix)
> > 6. need pbuffer support implemented for the future (we need to be
> > able to render to an intermediate buffer)
> > 7. if the window is fullscreen glx may choose to do page flipping
> > not copy from back to front buffer. in this case evas's assumption
> > that the buffer was exactly as it left it when it last rendered is
> > wrong - as it actually is as it was rendered 2 frames ago, not the
> > last frame.
> There is also a problem when you have several windows using the GL
> engine in your program, but I think it's probably a problem with
> Ecore_Evas_GL. The Glitz engine that raster seems to be writting
> should fix most of these problems :)
> 
> 
> Regards :)
> Simon
> 
> 
> 
> 
> On Sun, 12 Nov 2006 12:40:37 +0100,
> Rene Jensen <centipede@takhis.net> wrote :
> 
> > WARNING: LONG POST AHEAD...
> > 
> > (Sigh) After having posted on both IRC and the webforum, I get the 
> > distinct feeling that this community has been worn down by daft
> > requests for getting fancy window drawing using OpenGL.
> > 
> > This is a serious shame because now even the smallest utterance of
> > that API makes it's author look guilty. The developers forget that
> > end-users asking for something XGL'ish is a far cry from application
> > developers asking for their favorite API for graphics/GLGPU
> > programming, which they need to make video/3D applications using
> > Ewl/Etk.
> > 
> > However, as an application developer, I feel that:
> > 
> > 1) Etk/Edje is perfect for the job. The efficiency is the reason I
> > am choosing E if I can get away with it in the first place. I need a
> > strong and themable GUI. I *LOVE* Efl's well-organized style!
> > 
> > 2) The window manager and graphics lib should NOT squander my
> > precious GPU cycles on needless features. If I could make a 3D in a
> > console window, I'd do that.
> > 
> > 3) An extra GL layer is actually another source of errors! Once I
> > made a small 3D paint-program that used GL for the painting
> > procedures, http://artcamilla.dk/centipede. I spend a LOT of time
> > tracking down a bug in Windows where I use Nvidias desktop switcher.
> > All that was drawn on my screen was a frame delayed. Turned out that
> > when I switched off the desktop switcher or even turned off screen
> > rotation (I have a tablet-pc), the bug dissappeared. Wasn't in my
> > program after all. Incidently, the above mentioned program used my
> > own OpenGL based mini-GUI. Guess why I am looking for another GUI
> > with a strong support of themes ;-)
> > 
> > 4) It will be hard to write any program at all in the video/3D
> > industry without having support for OpenGL.
> > 
> > --------------------------------
> > 
> > Ok, enough ranting. This is a verbatim copy of the forum post I made
> > few days ago. By the end of this mail, I have already answered some
> > of it:
> > 
> > --------------------------------
> > 
> > I've learned that OpenGL requests falls in two camps this place:
> > Those for a way to put Evas into OpenGL (for kicks), and those for a
> > way to put OpenGL into Evas/Etk (for making any kind of serious
> > multimedia program). This post belongs in the latter camp.
> > 
> > Without in any way claiming to be a proficient E programmer, I've
> > taken the liberty to scout for the possibility of drawing 3D in ETK,
> > since it appears to be a non-existing feature right now. Hope I
> > won't make too big a fool of myself ;-)
> > 
> > Basically all that is needed to be able to draw using opengl in X is
> > the creation of a GL context using GLX. The only thing required is
> > that you have a handle to an X drawable (Window or Pixmap). I can
> > see that in E getting this handle is less obvious, since E is
> > unaware of a specific render-backend. Opposite GTK which has an X
> > Window for each widget, ETK renders each element directly to a
> > buffer, and only this grand superbuffer has an associated Window -
> > if using some kind of X11 backend of course. If I read the code
> > correctly, the Evas software-X11 backend actually renders to a
> > pixbuf in shared-memory.
> > 
> > So far so good. I traced this Drawable to a function called
> > 'eng_setup', which is handed an X Drawable (amongst other things).
> > Though I can't see where this Drawable is created since I don't know
> > who CALLS eng_setup, I guess it would still be possible to get the
> > super-drawable somehow.
> > 
> > So I guess that in order to get OpenGL support in ETK, three things
> > are needed:
> > 
> > 1) Access the Drawable for the root Evas (if using X11/GLX) or a
> > Window (if using GDI/WGL on windows)
> > 
> > 2) Knowledge about where in the root-evas the widget which on which 
> > OpenGL drawing should occur is placed.
> > 
> > 3) Cooperation from ETK: It shouldn't paint anything to update that 
> > widget and it should make it possible to emit a "paint" signal so
> > the user can emit the proper set of OpenGL commands.
> > 
> > Getting 2. to work should be easy. Accessing the Drawable in 1 is
> > not at all impossible either, I guess. (save the Drawable in a
> > global var in some of the E libraries and get it through a
> > function. As to 3., it is more of a mystery exactly how, but
> > perhaps somebody sees the light more clearly.
> > 
> > Before I go on, I'd like your sentiments on this
> > request/suggestion. Presumable somebody will cry: "No way!  E has
> > nothing to do with OpenGL period! This would violate the API which
> > is totally architecture agnostic, you ignorant philistine", which
> > is a perfectly adult way of opening this interesting discussion.
> > Other people may ask why I am not simply using this ...XXX...
> > GL-widget. I certainly hope that happens ;-)
> > 
> > 
> > --------------------------------
> > 
> > And a few more thoughts (and solutions) I have since made:
> > 
> > 1) I can see a problem if Evas uses some form of buffering. Then
> > you need to pump out the data from the GL context. This may not be
> > as slow as it sounds on modern architectures and if the updating of
> > the cache doesn't happen every time a single bit has been changed.
> > 
> > 2) A spin on the above. In case Evas buffers use that cache, it is
> > going to be hard to emit some kind of "paint" signal which will be
> > needed to draw opengl into the canvas. However I studied Evas' code
> > and I can see that the engine-module simply get a
> > 
> >     eng_image_draw (in modules/engines/gl_x11/evas_engine.c)
> > 
> > which converts into a
> > 
> >     evas_gl_common_image_draw (in
> > modules/engines/gl_common/evas_gl_image.c)
> > 
> > In the last function, the is evident that the Image being painted
> > is actually a GL texture. So a quick solution could be to use GL's
> > recent Render-To-Texture mechanism (a.k.a Framebuffers) to make the
> > Image being juggled with an actual 3D image rendered at users will
> > (as long as (s)he remembers to tell Evas that the "image" has
> > changed). Not the fastest solution, but not bad either. The
> > programmer is unburdened with "paint" calls, and Evas is free to
> > repaint and buffer as it sees fit.
> > 
> > 
> > Responding to my own statements earlier:
> > 
> > 1) We already have access to the Drawable from the program's main 
> > function, which sets up the environment. I missed that because it
> > seems etk_init handles it. Thus etk_init needs to open up a bit.
> > 
> > 2) If you use Render-To-Texture, you don't need anything from Etk
> > except access/modification possibility of it's GLuint that holds the
> > texture name
> > 
> > 3) - ditto -
> > 
> > 
> > Caveat's:
> > 
> > 1) You still need the GL CONTEXT that get's created. For some
> > reason this isn't dont in the main function, e.g.
> > 
> >     bin/evas_gl_x11_main.c
> > 
> > 2) You need to be able to get the GLuint of an image.
> > 
> > 3) This is inherently ENGINE SPECIFIC. No sense in asking for a 
> > texture-id from a cairo backend.
> > 
> > 
> > --------------------------------
> > 
> > And something completely different:
> > 
> > I have good experience with OpenGL and a small GDI/GL + X/GL 
> > cross-platform GUI behind me. I couldn't help noticing that your 
> > Win32/GDI engine files are almost empty. Just ask if you need any
> > tips. I might be able to help. I also have a somewhat deep
> > understanding of OpenGL Framebuffer Objects and all that "weird"
> > OpenGL stuff.
> > 
> > Oh, and don't use the GDI way of transferring buffered graphics data
> > to a window (Device Independent Bitmap). Slow like hell. Either use
> > a GL context (why not?) or DirectX. I don't know anything about
> > GDI+ or the new stuff from MS.
> > 
> > 
> > 
> > Ahem, I should stop talking.
> > 
> > 
> > Regards Centipede (Rene Jensen)
> > 
> > 
> > -------------------------------------------------------------------------
> > Using Tomcat but need to do more? Need to support web services,
> > security? Get stuff done quickly with pre-integrated technology to
> > make your job easier Download IBM WebSphere Application Server
> > v.1.0.1 based on Apache Geronimo
> > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
> > _______________________________________________ enlightenment-devel
> > mailing list enlightenment-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
> > 
#include <stdlib.h>
#include <stdio.h>
#include <Evas.h>
#include <Ecore.h>
#include <Ecore_Evas.h>
#include <GL/gl.h>
#include <GL/glu.h>

#define WIDTH 800
#define HEIGHT 600

static int _animator_cb(void *data);
static void _flush_cb(Evas *e);

int main(int argc, char *argv[])
{
   Evas *e;
   Ecore_Evas *ee;
   Evas_Object *bg;
   Evas_Object *rect;
   
   evas_init();
   ecore_init();
   ecore_evas_init();
   
   ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, WIDTH, HEIGHT);
   ecore_evas_size_min_set(ee, WIDTH, HEIGHT);
   ecore_evas_size_max_set(ee, WIDTH, HEIGHT);
   e = ecore_evas_get(ee);
   evas_flush_callback_set(e, _flush_cb);
   ecore_evas_show(ee);
   
   
   /* We create a black background rect because Evas doesn't clear the color buffer */
   bg = evas_object_rectangle_add(e);
   evas_object_color_set(bg, 0, 0, 0, 255);
   evas_object_move(bg, 0, 0);
   evas_object_resize(bg, WIDTH, HEIGHT);
   evas_object_show(bg);
   
   /* The rectangle is here to show that Evas can render object while OpenGL is also rendering */
   rect = evas_object_rectangle_add(e);
   evas_object_color_set(rect, 0, 200, 180, 255);
   evas_object_move(rect, 10, 10);
   evas_object_resize(rect, 30, 30);
   evas_object_show(rect);
   
   /* By default, an animator is 30 times per second */
   ecore_animator_frametime_set(1.0 / 60.0);
   ecore_animator_add(_animator_cb, e);
   ecore_main_loop_begin();
   
   ecore_evas_shutdown();
   ecore_shutdown();
   evas_shutdown();
   
   return 0;
}

/* Forces Evas to redraw */
static int _animator_cb(void *data)
{
   Evas *e;
   
   if (!(e = data))
      return 1;

   evas_damage_rectangle_add(e, 0, 0, WIDTH, HEIGHT);
   return 1;
}

/* This is called before glXSwapBuffers() gets called.
 * The calls to the GL API have to be placed here */
static void _flush_cb(Evas *e)
{
   static float rot = 0.0;
   
   glPushAttrib(GL_ALL_ATTRIB_BITS);
   
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   /* We have to disable the scissor test or sometimes it's not rendered. Not sure why... */
   glDisable(GL_SCISSOR_TEST);
   glEnable(GL_CULL_FACE);
   glCullFace(GL_BACK);
   
   glClear(GL_DEPTH_BUFFER_BIT);
   
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();
   gluPerspective(45.0, (float)WIDTH / (float)HEIGHT, 0.1, 100.0);

   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity();
   
   glTranslatef(0.0, 0.0, -5.0);
   glRotatef(rot, 0.3, 0.6, 0.0);
   glBegin(GL_QUADS);
      /* Top of cube */
      glColor3f(0.0f, 1.0f, 0.0f);
      glVertex3f(1.0f, 1.0f, -1.0f);
      glVertex3f(-1.0f, 1.0f, -1.0f);
      glVertex3f(-1.0f, 1.0f, 1.0f);
      glVertex3f(1.0f, 1.0f, 1.0f);
      /* Bottom of cube */
      glColor3f(1.0f, 0.5f, 0.0f);
      glVertex3f(1.0f, -1.0f, 1.0f);
      glVertex3f(-1.0f, -1.0f, 1.0f);
      glVertex3f(-1.0f, -1.0f, -1.0f);
      glVertex3f(1.0f, -1.0f, -1.0f);
      /* Front of cube */
      glColor3f(1.0f, 0.0f, 0.0f);
      glVertex3f(1.0f, 1.0f, 1.0f);
      glVertex3f(-1.0f, 1.0f, 1.0f);
      glVertex3f(-1.0f, -1.0f, 1.0f);
      glVertex3f(1.0f, -1.0f, 1.0f);
      /* Back of cube */
      glColor3f(1.0f, 1.0f, 0.0f);
      glVertex3f(-1.0f, 1.0f, -1.0f);
      glVertex3f(1.0f, 1.0f, -1.0f);
      glVertex3f(1.0f, -1.0f, -1.0f);
      glVertex3f(-1.0f, -1.0f, -1.0f);
      /* Right side of cube */
      glColor3f(1.0f, 0.0f, 1.0f);
      glVertex3f(1.0f, 1.0f, -1.0f);
      glVertex3f(1.0f, 1.0f, 1.0f);
      glVertex3f(1.0f, -1.0f, 1.0f);
      glVertex3f(1.0f, -1.0f, -1.0f);
      /* Left side of cube */
      glColor3f(0.0f, 1.0f, 1.0f);
      glVertex3f(-1.0f, 1.0f, 1.0f);
      glVertex3f(-1.0f, 1.0f, -1.0f);
      glVertex3f(-1.0f, -1.0f, -1.0f);
      glVertex3f(-1.0f, -1.0f, 1.0f);
   glEnd();
   
   /* Restore the previous transform matrices */
   glPopAttrib();
   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
   
   rot += 1.0;
}