From: Carlos L. G. <gen...@gm...> - 2012-06-22 06:33:02
|
Hi there! Some bits of the latest coding/researching I'm doing: I've started to port Context::accelerated_render to a template framework. Context::accelerated_render has been overloaded to admit Surface and CairoSurface. Then each version should call the template Context::accelerated_render_ (notice the underscore) using CairoSurface or Surface. This way the code created to render on a Surface is reused for any of both. In the template the Surface has been replaced by the corresponding typename 'S' and the Color is replaced by 'typename S::value_type' when used as type and by 'S::value_type::' when used as name space solver. See commit here: https://github.com/synfig/synfig/commit/f9ca7f3a5f2649087a9495a67b786f3c4b4d02aa Notice that the Context::accelerated_render CairoSurface version just returns true. This is because it can call the template only when the template can be instantiated with CairoSurface. In some point in the middle of the Context::accelerated_render_ template, the layer->acceerated_render is called so if it is not ported to allow to use CairoSurface it is not possible to instantiate the template with CairoSurface. In my local branch I've started to port the next one needed member function to port: Layer::accelerated_render When I did something similar of what I did for Context::accelerated_render I found on very difficult problem to solve: circular references on the class includes. Layer::accelerated_render_ template has to be written on the class header file (layer.h) and there it needs the #include "context.h" to be added. This is caused by that Layer::accelerated_render uses a Context operator '--' so the complete specification of the Context class is needed (not the forward declaration of the class is enough). But if you include context.h in layer.h it happens that context.h needs Layer class definition as well (it uses layer->accelerated_render, remember) so a circular include happens and it is not possible to compile in that way. Solutions? Add a new class that warp the Layer::accelerated_render_ template and place it on other file. I tried it but still having same circular reference... The reason for port to a template the Layer::accelerated_render member is to avoid rewrite code twice. But in this case the code is so simple and short so I decided to rewrite the code using CairoSurface instead... But... Why do I want to port to template the accelerated_render member for each layer? It is because my initial wish it to render any layer into a image CairoSurface regardless if the Cairo high level API accelerated_render has been alredy written. This way it will be possible to test mixed render system (on a CairoSurface but using mixed software method and Cairo API) from the start. Looks like that approaching is not possible because every accelerated_render defined in any layer has the context.accelerated_render(surface,quality,renddesc,&supercb) called (that is, render the context on the surface first, before render the layer itself.... What happen if I move context class definition inside layer.h header??? That would allow to use context completely in the layer.h header and so I would save a lot of code duplication! Any though about whether it is a good or bad idea?: Move Context class definition to layer.h and move Context class implementation to layer.cpp or leave it on context.cpp and fill context.h with a single #include "layer.h" Cheers! 2012/6/17 Carlos López González <gen...@gm...>: > Hi! > I'm sorry for force the situation to use a generic class that supports > both color types. IT IS NOT POSSIBLE TO HANDLE IT IN THE CURRENT > SITUATION. Currently, layers rendering methods assume that always > Surface is returning Color (in opposite to CairoColor) when asking to > Surface. This would make not possible to reproduce the rendering > method for any type of color unless each layer rendering method is > rewritten again. If so, why to force to Surface to support both color > types. Just re-write the rendering method using CairoColor when > needed. > > So, I get back to continue developing CairoSurface and after that I > will deploy the accelerated_render method that gets an extra parameter > to decide for one render method or other. Maybe, it worths to create a > internal template accelerated_render member to use Color or CairoColor > and so, it is not needed to code it twice so if there is a improvement > or a bug fix it is made for both at the same time. > > The story of the commits that I did to try to implement the double > inheritance solution is at genete_new_cairo_core branch. From now on > I'll continue with the mentioned above ideas using > genete_new_cairo_core_2 > > If someone has one other better idea please let me know. Requisites are: > 1) When a layer is not supported by Cairo libraries, its rendering > method should use directly the cairo provided image surface data. This > would avoid useless Color to CairoColor conversion and vice-versa on > each layer of that type. > 2) When a layer is supported by Cairo libraries, use the Cairo API > when possible. > > Thanks! > > 2) > > 2012/6/11 Carlos López González <gen...@gm...>: >> Ok, finally I figured out the best way to handle the multiple Surface >> support in Synfig. >> The idea is that really there is not need to have a CairoSurface. >> Instead of that it is better to derive the current synfig::Surface >> from the etl template for Color and also from the etl template from >> CairoColor. By default Surface is a SOFTWARE surface and would use >> Color class. It is needed to extend the Surface behavior adding: >> >> 1) One enum value to tell what's the type of surface: SOFTWARE, CAIRO, >> OPENGL, etc. >> 2) As the Surface derivates from two similar templates it might cause >> ambiguities when a member function is called and not Color or >> CairoColor is involved. In those cases the ambiguity has to be solved >> internally by Surface using the previous defined type in a switch/case >> statement. >> 3) Surface would only admit Color as interface to pass color values. >> If the Surface is a Cairo surface then it will convert it to >> CairoColor on the fly. >> 4) Surface would hold a cairo_context_t pointer to allow to use high >> level API form Cairo. >> 5) When a Surface type CAIRO, is asked to use low level painting >> operations, it asks to cairo_context_t to provide the image surface, >> before paint, and will pass the image surface to the cairo_context_t >> once the painting operations are finished. This might be done using >> some kind of map/unmap commands, mandatory to write on the current >> cairo_surface_t using the non Cairo API and send it back to it, once >> finished. >> 6) The responsible of create the cairo_context_t from a >> cairo_surface_t pointer is the derived target. The derived target will >> create the proper cairo_surface_t backend based on the target type and >> if there is any backend supported (png, svg, pdf, opengl, x11, quarz, >> Win, ...) >> >> Please any comment is welcome. >> Cheers! >> >> 2012/6/10 Carlos López González <gen...@gm...>: >>> Better than extend Surface to derive from the two etl implementations >>> (for Color and for CairoColor) make a new class derived from Surface >>> and CairoSurface. >>> The inheritance diagram could be like this: >>> >>> etl::surface<Color, ColorAccumulator, ColorPrep> <----------Surface >>> >>> etl::surface<CairoColor, CairoColor, CairoColorPrep> <-----------CairoSurface >>> >>> Surface <------------\ >>> <-------- SuperSurface >>> CairoSurface <-----/ >>> >>> So the SuperSurface is a Surface and a CairoSurface at the same time. >>> Later we can rename Surface to SynfigSurface and SuperSurface to >>> Surface, making the interface clean for the layers. >>> That SuperSurface should decide which ancestor member function to call >>> based on the render method (that should be passed at creation time). >>> If the ancestor member uses Color or CairoColor, as parameter, we can >>> accept Color always and then pass the Color or a calculated CairoColor >>> based on the render method. >>> >>> It looks complex to handle but I think it is worth to look at. >>> Cheers! >>> >>> 2012/6/10 Carlos López González <gen...@gm...> >>>> >>>> Hi! >>>> You might have noticed that there are some new commits on the genete_new_cairo_core branch. In the last few days my mind has been boiling facing some problems on the strategy I planned for the Cairo render implementation. >>>> >>>> One of the things that bugs me more of the original strategy, is that there were needed to convert the pixels from one format to Cairo format in several places because the render is made on the Synfig surface. >>>> >>>> I tried to fix this doing the following steps: >>>> 1) Define a CairoColor class with the same interface that Color class has. Currently is a separated definition but it can be done using a template as eldruin is doing it his own branch. >>>> 2) Using CairoColor define a CairoSurface class that has similar interface than the synfig Surface class and so it can be used to render the document using a CairoSurface but the SOFTWARE render method. The idea was to make both classes handled by one ancestor one and use the ancestor as the class to pass to the render routines. In practice it wouldn't be possible unless the ancestor class has both CairoSurface and Surface interface members implemented as virtual. In any case, the render methods should extract the type of surface to decide which interface to use making it not transparent. So at the end, it is needed to modify all the render functions to use one or other class and the idea of transparency of the CairoColor integration fails. >>>> >>>> So I've came up with a new idea. Surface is currently inherited from etl::surface<Color, ColorAcumulator, ColorPrep> (all based on Color class). What if I extend the Surface class to inherit from etl::surface<Color, ...> and also from etl::surface<CairoColor, ...> ? >>>> This way, this super surface would use one or other interface depending on the render method passed at time of creation. >>>> >>>> I think that it would solve the interface problems because the distinction between one or other color type is handled internally by this super Surface class and the layers only need to tell the surface that the geometry has to be painted on it. In fact the layers shouldn't need to know the type of color that Surface holds. >>>> >>>> I need to review this idea deeply. Please stay tuned. >>>> Cheers! >>>> -- >>>> Carlos >>>> http://synfig.org >>>> >>> >>> >>> >>> -- >>> Carlos >>> http://synfig.org >> >> >> >> -- >> Carlos >> http://synfig.org > > > > -- > Carlos > http://synfig.org -- Carlos http://synfig.org |