I would maybe consider enforcing a fixed tuple size that is sent to the function. The cost of dynamically unpacking and checking the length of each might be detrimental (benchmark, maybe?)
It would take a sequence of tuples which match up with the blit arguments.I feel we should call it "Surface.blits". To go with drawline/drawlines.Hello,this blit_list, blits, blit_mult, blit_many call...
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:It can *not* handle (but would anyone care?):
- 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.
- blit many surfaces, to many other surfaces.
Areas not included in the scope of this:
- This could be used by two sprite groups quite easily (Group, RenderUpdates). But I think it's worth trying to compile the sprite groups with Cython instead, as a separate piece of work.
- Multi processing. It should be possible to use this API to build a multi process blitter. However, this is not addressed in this work. The Surface we are blitting onto could be split up into numberOfCore tiles, and rendered that way. This is classic tile rendering, and nothing in this API stops an implementation of this later.
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)