From: Carsten H. (T. R. <ra...@ra...> - 2002-06-17 01:30:42
|
On Fri, 14 Jun 2002 21:33:30 +0200 Till Adam <ti...@ad...> babbled: > I dont really see why that would be any cleaner than having one setup call per > engine, considering the fact that the number of engines will likely be less > than maybe 10. With the void * and structs solution you'll have to trust the > user to fill in that struct correctly and not forget about a member and then > access it more or less blindly, whereas a function signature get checked by > the compiler. So I think its less safe and its not less work. ok. i have a plan.. well.. too late. i implemented it... ok - however we look we can't get the compiler to do it all for us. basically because that's done compile time.. bu the lib may change runtime (ie the lib may be recompiled with or without other engines at some later date etc. and the app should not need a recompile, and vice-versa). eg: app is compiled to use dfb engine OR x11. you download app. it won't even be able to start because even though it might not be configured to use the dfb engine it has references to dfb engine symbols for dfb engine init/query etc. it won't even get past ld.so. so... we're screwed however we look at it. (i've spent the last few days looking at it many ways). i've taken suggestions to mind and think i have a good compromise that keeps it all very very clean. i suggest checking out my commit. now init is done via an engine-specific struct (that i need to break the definition of out into its own engine specific header). now it's fairly simple yet massively expandable and flexible. app wants to use engine X app queries for a listing of engines and see if X is in it.if it isn't it can try another engine it knows about - or cleanly abort. if it's there then the app knew about it compile time and has its header for its inti struct. it gets the init struct from the evas, fills it in, can call functions that are set up in the struct by the enigne to get information... and then pass struct back in (evas internally checks that its the same struct and not some dummy new one that didn't come from the evas - it's not foolproof - but will get the majority of cases). and then evas can init from that info. ie: Evas *evas; Evas_Engine_Info_Software_X11 *einfo; evas = evas_new(); evas_output_method_set(evas, evas_render_method_lookup("software_x11")); evas_output_size_set(evas, win_w, win_h); evas_output_viewport_set(evas, 0, 0, win_w, win_h); einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(evas); einfo->info.display = disp; einfo->info.visual = einfo->func.best_visual_get(disp, screen); einfo->info.colormap = einfo->func.best_colormap_get(disp, screen); einfo->info.depth = einfo->func.best_depth_get(disp, screen); einfo->info.drawable = win; einfo->info.rotation = 0; evas_engine_info_set(evas, (Evas_Engine_Info *)einfo); our engine specific header has: /* FIXME: this should go into another .h file the app needs to include like */ /* Evas_Engine_Software_X11.h */ typedef struct _Evas_Engine_Info_Software_X11 Evas_Engine_Info_Software_X11; struct _Evas_Engine_Info_Software_X11 { /* PRIVATE - don't mess with this baby or evas will poke its tongue out */ /* at you and make nasty noises */ Evas_Engine_Info magic; /* engine specific data & parameters it needs to set up */ struct { Display *display; Drawable drawable; Visual *visual; Colormap colormap; int depth; int rotation; } info; /* engine specific function calls to query stuff about the destination */ /* engine (what visual & colormap & depth to use, performance info etc. */ struct { Visual * (*best_visual_get) (Display *disp, int screen); Colormap (*best_colormap_get) (Display *disp, int screen); int (*best_depth_get) (Display *disp, int screen); Evas_Performance *(*performance_test) (Evas *e, Display *disp, Visual *vis, Colormap cmap, Drawable draw, int depth); void (*performance_free) (Evas_Performance *perf); char * (*performance_data_get) (Evas_Performance *perf); char * (*performance_key_get) (Evas_Performance *perf); Evas_Performance *(*performance_new) (Evas *e, Display *disp, Visual *vis, Colormap cmap, Drawable draw, int depth); void (*performance_build) (Evas_Performance *perf, const char *data); void (*performance_device_store) (Evas_Performance *perf); } func; }; now there are no symbol problems. we still rely on the app properly checking the einfo is not NULL (sorry i don't check here - but if the app initialized an evas with an engine id it doesn't handle einfo WILL be NULL) and relies on the struct not being mutilated and the app passing it back properly, but all in all it's about the cleanest method i can come up with that supports querying of the engine, passing in of parameters, and can survive the app and lib having different ideas of what engines are included, as long as the app "plays nice" and checks for the engine it wants. > If you do what you suggest and go the struct and void* route, you could always > use the same approach and just have one query call which returns a void* to > the init struct. Just as unsafe, though. ;) yup, but as i said - i can't think of anything thats safe AND would survive the lib and app having different compilations of engines at the end of the day i think i'd rely on a higher level library that would encapsulate the basics of the target windowing system and its event system and an event loop that would "do the right thing" here at this interface level, and take the work from the app. -- --------------- Codito, ergo sum - "I code, therefore I am" -------------------- The Rasterman (Carsten Haitzler) ra...@ra... ra...@de... Mobile Phone: +61 (0)413 451 899 Home Phone: 02 9698 8615 |