Hi, I will do just a quick answer, I don't know if I will have time to come back on this subject later.
On Wed, Mar 2, 2011 at 5:41 AM, Sung W. Park <[email protected]> wrote: > Hi all, > > In my earlier post, I've discussed about the issues with getting the > > evas_object_image_native_surface_set(..., Evas_Native_Surface *surf); > > function for setting OpenGL output texture. > > The main issue was the GL application having to know Evas' GL context for > resource > sharing. (refer to the older post if this doesn't make sense). Exposing > Evas' > GL context is just a bad idea and it makes things really ugly. > > One idea that Cedric mentioned as a response was to have evas provide APIs > that create OpenGL context for the user so everything can be hidden. > > I actually had the same idea and the previous post was a way for me to setup > a > discussion ground for what I'm about to propose. > > Instead of just exposing apis for creating contexts, I thought it would be > nice > for Evas to provide the OpenGL glue layer for the user. When I say glue > layer, > I'm talking about GLX (for X evn in linux), WGL (for windows) and CGL (for > mac). > The Evas glue layer would provide functions such > as surface/context creation, make current function and etc. this allows > evas to > hide all the backend specific code in the evas engine and have user deal > with > the provided APIs. This goes along with EFL philosophy I believe. > > For surface implementation, the engine can simply create an FBO and a > render target texture for the user to render to. The texture can be used to > for setting the native_surface function. > > There are two way to go about providing the APIs. One approach is to have > evas fill out a list of functions from the engine. This can be similar to > Evas_Engine_Info_GL_X11. > > for example, > //--------------------------------// > // Option 1 > struct _Evas_GL_Info > { > int version; > > struct { > Display *display; > Evas_GL_API api; > } info; > > struct { > Evas_GL_Contex *(*create_context)(Evas_GL_Info *info); > Evas_GL_Surface *(*create_surface)(Evas_GL_Info *info, const > Evas_GL_Config *config); > Eina_Bool (*make_current)(Evas_GL_Info *info, > Evas_GL_Context *context, Evas_GL_Surface *surface); > Evas_GL_Func (*get_proc_address)(const char *proc_name); > const char *(*query_extension)(void); > // Need functions that destroy contexts and etc... > } func; > }; > > EAPI Evas_GL_Info *evas_gl_info_get(Evas *e); > > // Usage Example > int main() > { > Evas e* = ...; > > Evas_GL_Info *glinfo; > Evas_GL_Context *ctx; > Evas_GL_Surface *sfc; > Evas_GL_Config cfg = {...}; > Evas_Native_Surface ns; > > glinfo = evas_gl_info_get(e); > ctx = glinfo->func->create_context(glinfo, EVAS_GL_API_GLES_2); > sfc = glinfo->func->create_surface(glinfo, cfg); > > glinfo->func->make_current(glinfo, ctx, sfc); > > // Use tex and the info in the surface to attach it to the image_object > ns.data.opengl.texture_id = sfc->data.gl.tex; > ... > > return 0; > } > > //--------------------------------// > Another option is to provide evas-like APIs. > > // Option 2 > EAPI Evas_GL *evas_gl_new (Evas > *e); > EAPI Evas_GL_Surface *evas_gl_surface_create (Evas_GL *evas_gl, > Evas_GL_Config *cfg, int w, int h); > EAPI Evas_EFGL_Context *evas_gl_context_create (Evas_GL *evas_gl); > EAPI Eina_Bool evas_gl_make_current (Evas_GL > *evas_gl, Evas_GL_Surface *sfc, Evas_EFGL_Context *ctx); > EAPI Evas_GL_Func evas_gl_proc_address_get (Evas_GL *evas_gl, > const char *name); > > EAPI Eina_Bool evas_gl_native_surface_get (Evas_GL > *evas_gl, Evas_GL_Surface *sfc, Evas_Native_Surface *ns); > > // Usage Example > int main (void) > { > Evas e* = ...; > > EvasGL *evasgl; > EvasGL_Surface *sfc; > EvasGL_Context *ctx; > EvasGL_Config cfg = { ... }; > Evas_Native_Surface ns; > > evasgl = evasgl_get(canvas); > sfc = evasgl_create_surface(evasgl, &cfg, w, h); > ctx = evasgl_create_context(evasgl); > > evasgl_make_current(evasgl, sfc, ctx); > > // GL Calls... > ... > > // Get the native surface from EvasGL surface to attach it to the image > object > evasgl_native_surface_get (evasgl, *sfc, &ns); > ... > } > > //--------------------------// > Personally, I like the option 2 because the APIs look more Evas-like and > it's evas engine neutral. I really do prefer the second one. Sounds much more evas like. But did you consider just defining a new evas object ? Thinking about that solution, I do think it will create more work than you second solution without much gain. Just wanted to know your opinion on that subject. > Now, there are a few issues with implementing a glue layer in Evas. > > - One major issue is that internally, the surface that the evas provides is > implemented using an FBO. Semantically, FBO index 0 is the main framebuffer > of the screen. So, when user calls, glBindFramebuffer(GL_FRAMEBUFFER, 0); > the user expects the framebuffer of the surface. Unfortunately, this isn't > true > when using the evas provided surface. So we'll need to either advise > developers > not to call glBindFramebuffer(GL_FRAMEBUFFER, 0) or hook that > function and have it do what we want to do. Another idea that came up is > have evas provide a list of GL functions that it supports. That can be > debated later. Hum, maybe the question is when does someone using Evas try to call that function and when do we want it to mean something. I have not much opinion about this one. > - Another issue is that because the application would run in the same thread > as evas, > the GL application would need to do a make_current every time he wants > something > drawn. This is because there is a context switch when Evas draws something > to > its output canvas. We can consider rendering it in a different thread but > my understanding is that Evas is not MT safe. Hum, their is maybe another source of problem here. It should be possible in the futur to make the GL engine asynchronous, so it will run in another thread waiting for command prepared in the main thread. How will you handle that kind of case ? And you are right Evas function call should not be called from outside of the main thread. Regarding make_current, the main issue, as far as i understand, is that we expect it to be blocking until the image is rendered on screen, but if we do block in the main loop, evas render would never be called and we will never leave out of make_current... That's indeed an issue :-) Maybe we can hide this, by just notifying Evas about the change and the app would just wait for an EVAS_CALLBACK_RENDER_FLUSH_POST. But I highly dislike this kind of design as it will make existing engine difficult to integrate in evas at the moment (They will require to run in another thread waiting on a pipe after calling make_current for the event to wake them). On the long term, it would maybe not be that much problematic as Wayland is also promoting this kind of behaviour, so 3D engine would maybe adapt to this design. > I'm attaching a sample Evas_GL.h header and a sample program that would use > the apis. In the header, I've just filled out the config enums without > putting too much > thought into it so don't flame me for that just yet =) Also, I actually > have the above > headers implemented but I'll wait until the community decides on a set of > APIs and then submit a patch for review. > > comments would be much appreciated. thanks! I do prefer this example, it seems much cleaner and portable. Keep going forward, I know for sure that many people will love to see such feature in Evas ! -- Cedric BAIL ------------------------------------------------------------------------------ Free Software Download: Index, Search & Analyze Logs and other IT data in Real-Time with Splunk. Collect, index and harness all the fast moving IT data generated by your applications, servers and devices whether physical, virtual or in the cloud. Deliver compliance at lower cost and gain new business insights. http://p.sf.net/sfu/splunk-dev2dev _______________________________________________ enlightenment-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
