[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

blits proposal, was Re: [pygame] Dirty rect overlapping optimizations



Hello,

this blit_list, blits, blit_mult, blit_many call...

I feel we should call it "Surface.blits". To go with drawline/drawlines.
It would take a sequence of tuples which match up with the blit arguments.

The original Surface.blit API.
    http://www.pygame.org/docs/ref/surface.html#pygame.Surface.blit
  blit(source, dest, area=None, special_flags = 0) -> Rect

The new blits API.
    blits(args) -> [rects]
    args = [(source: Surface, dest: Rect, area: Rect = None, special_flags: int = 0), ...]
    Draws a sequence of Surfaces onto this Surface...

    :Example:
    >>> surf.blits([(source, dest),
                  
(source, dest),
                  
(source, dest, area),
                  
(source, dest, area, BLEND_ADD)]
    [Rect(), Rect(), Rect(), Rect()]



One potential option...
  • Have a return_rects=False argument, where if you pass it, then it can return None instead of a list of rects. This way you avoid allocating a list, and all the rects inside it. I'll benchmark this to see if it's worth it -- but I have a feeling all those allocations will be significant. But some people don't track updates, so allocating the rects is not worth it for them. eg. the implementation from Leif doesn't return rects.

It can handle these use cases:
  • blit many different surfaces to one surface (like the screen)
  • blit one surface many times to one surface.
  • when you don't care about rects, it doesn't allocate them.
  • when you do care about update tracking, it can track them.
It can *not* handle (but would anyone care?):
  • blit many surfaces, to many other surfaces.

Areas not included in the scope of this:


Enhancements, objections?



cheers,





On Mon, Mar 27, 2017 at 6:38 PM, René Dudfield <renesd@xxxxxxxxx> wrote:
Cool about the blit function. Since the rect and surfaces are by reference, then you only need to make sprite_image_list once (if you are blitting the same thing every time). Additionally, I think it would likely be fast enough for another commonly requested case (blit the same image to many different spots). It would also work nicely for sprite groups. I think it's worth some more API discussion, before merging it in. We'd also need some tests and docs.



On Mon, Mar 27, 2017 at 4:59 PM, Leif Theden <leif.theden@xxxxxxxxx> wrote:
I think a function that accepts a sequence of tuples in the form of (dest_surface, dest_position, source_area, blend_mode) would be enough.  It is only needed as a power-user optimization and I don't seem much value in watering it down or splitting it into multiple functions for beginners.  No need to overthink and complicate it.  Cython may help sprite rendering in Groups, but it would have to be implemented and tested.

Has anyone considered releasing the GIL during blit operations?  Is it possible the release the GIL during a blit, then block when needed, in the cases of subsequent draw operations?  The optimized case would be to allow math operations to execute while the display buffer is being modified, while you are iterating over sprites.

Here is my preliminary C code for a "blit_multi" function.  It is called "blit_list".  It only supports (dest_surface, dest_position) tuples, but it works as so far.
https://gist.github.com/bitcraft/1785face7c5684916cde

Use it like this:

sprite_image_list = [(s.image, s.rect) for s in self.sprites]
display.blit_list(sprite_image_list)