Hi Cedric, On Thu, Mar 3, 2011 at 1:30 AM, Cedric BAIL <[email protected]> wrote:
> Hi, > > I will do just a quick answer, I don't know if I will have time to > come back on this subject later. > that's fine. =) > > 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. > Yes, that's exactly why I didn't go with the evas object. I didnt' think it was necessary and there wouldn't be much gain if not overhead. > > > 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. > We'll need to figure this one out eventually. Evas providing a list of GL functions that it supports may not be a bad idea either. EVAS_GL_API *gl_api; evas_gl_get_api(evas_gl, gl_api); gl_api->glBindFrameBuffer(GL_FRAMEBUFFER, 0); gl_api->glBegin(GL_TRIANGLES); gl_api->glVertex3f(0.f, 0.f, 0.f); ... Then we can add logic that takes care of the glBindFrameBuffer issue. This can be debated more later. The initial implementation doesn't take this route but it can be added very easily. > > > - 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. > I guess having Evas thread-safe would be nice... But since it's not, we'll have to think about this a little more. For now, we'll just have to live with the make_current overhead. > 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 not sure if i'm following you on this about never leaving out of make_current in the main loop. make_current essentially does a gl context switch and it's just expensive to switch states from one set to another since GL is a state machine. internally, it would require a flush of the previous contexts' rendering commands. it's just something that's frowned upon to do many make_currents in a gl application. > > > 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 ! > I have the code running for the gl_x11 backend. i'll need to run some tests for egl path. hopefully I'll submit a patch for review soon thanks for your comments! > -- > Cedric BAIL > cheers, Sung ------------------------------------------------------------------------------ What You Don't Know About Data Connectivity CAN Hurt You This paper provides an overview of data connectivity, details its effect on application quality, and explores various alternative solutions. http://p.sf.net/sfu/progress-d2d _______________________________________________ enlightenment-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
