Nice, the code's coming together! I played around with it today and
fixed a couple of compile errors.

The structure feels good, I just have a few suggestions:
1) start_frame() and end_frame() feel redundant.

The purpose they serve in the scanline target is to signal the start
and end of data transfer from the Surface onto the underlying target.
The reason they're two separate methods is that in between,
start_scanline() and end_scanline() are called repeatedly. The cairo
renderer doesn't operated on scanlines, so I suggest a new structure:

-- obtain_surface() does all of the initialization related to the
beginning of a new frame, and returns either a surface or NULL, in
case of failure.
-- add_frame() takes the finished surface, transfers the data wherever
it needs to go, and destroys the surface

2) obtain_surface() should return cairo_surface_t* instead of
CairoSurface. The targets don't need the etl::surface API. It feels
redundant to have them wrap a cairo_surface_t* in a CairoSurface at
the start of the render, extract the cairo_surface_t* at the end of
the render, and not use any of the CairoSurface methods.

3) I think map_cairo_image and unmap_cairo_image should be private
methods that are called automatically on an as-needed basis.

One option is:
-- The CairoSurface constructor automatically maps the surface
-- new method: get_cairo_context() creates a context (cairo_t*) and
unmaps the surface
-- new method: release_cairo_context() deletes the context and remaps
the surface to an image

That way, the sequence of calls will look something like this:
* Create surface
* Map it to image
* Software render on some layers
* Cairo render on one layer
-- get_cairo_context() unmaps the image
-- cairo drawing operations on the context
     (all cairo drawing operations operate on a context, not on a surface!)
-- release_cairo_context() signals that drawing is done, surface is
remapped to an image
* Software render on some more layers
* Finish render

The other option is to optimize for the case where most layers can
render using cairo:
-- The CairoSurface constructor doesn't map the image
-- Calls to etl::surface API, (e.g. blit_to) map to image before
proceeding, and unmap when finished

Or a hybrid case:
-- Keep track of whether the last call was to the cairo or etl API
-- If the current call is to a different API, map/unmap the surface

Each of these options allows us to make map()/unmap() private methods,
so none of the rendering code will have to worry about calling them.


~Nikita

On Fri, Jun 29, 2012 at 3:30 AM, Carlos López González
<genet...@gmail.com> wrote:
> More news on the latest commits:
>
> The CairoSurface now holds a cairo_surface_t pointer. It is not
> possible to create the setl::surface part of the CairoSurface by the
> constructor. The CairoSurface only receives a cairo_surface_t on
> construction or later through a set_cairo_surface mmember call. To
> obtain a etl::sruface data form the CairoSurface it is needed to call
> the two new members map_cairo_image and unmap_cairo_image members. It
> would ask the cairo_surface_t to extract a cairo_surface_t image type
> and from it, the data pointer, the height, width and stride. It will
> allow to resize etl::sruface properly.
>
> Also, due to problems with Color class as returned as parameter in
> opposition to return a CairoColor, the use of Target_Scanline as
> ancestor of the derived Cairo targets is deprecated. Instead of that a
> new Target_Cairo derived from Target has been created. All the new
> coming Cairo Targets will derive from it.
>
> It is worth to mention that there is a virtual member in the
> Target_Cairo class called:
> CairoSurface* obtain_surface()
> Due to that CairoSurface now holds a cairo_surface_t that is the
> common pointer for all the Cairo backends, it is needed that the
> derived Cairo Target is the responsible of create a CairoSurface using
> the corresponding cairo_surface_t returned form the
> create_xxxx_surface() where xxxx depends on the particular Cairo
> backend handled by the derived Cairo Target.
> There are two other virtual members to start_frame and end_frame to
> allow the target to do the proper preparation tasks every time a new
> frame is going to be rendered.
>
> To complete this code session I created one target2cairosurface target
> that is the target to render directly on a CairoSurface using its
> etl::surface api. It will be used by Layer::accelerated_render and by
> synfig::render (well formerly synfig::cairorender in the next future)
> when the derived layer doesn't have accelerated_render defined (as
> happens in many layers that are deform type (noise distort, twirl,
> etc.)
>
> More to come hopefully in next days.
>
> Cheers!
>
> 2012/6/22 Carlos López González <genet...@gmail.com>:
>> 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 <genet...@gmail.com>:
>>> 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 <genet...@gmail.com>:
>>>> 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 <genet...@gmail.com>:
>>>>> 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 <genet...@gmail.com>
>>>>>>
>>>>>> 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
>
>
>
> --
> Carlos
> http://synfig.org
>
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and
> threat landscape has changed and how IT managers can respond. Discussions
> will include endpoint security, mobile security and the latest in malware
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
> _______________________________________________
> Synfig-devl mailing list
> Synfig-devl@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/synfig-devl

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Synfig-devl mailing list
Synfig-devl@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/synfig-devl

Reply via email to