[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: blits proposal, was Re: [pygame] Dirty rect overlapping optimizations
I think that special_flags could be shared for all the blits in the
list. I can't think of a case where I would want to use different flags
On Tue, 28 Mar 2017 23:54:32 -0500
Leif Theden <leif.theden@xxxxxxxxx> wrote:
> My votes:
> - don't bother with return value. If a person cared (probably
> doesn't), then the rects can be inferred from the list sent to
> Surface.blits() (again, not a fan of dirty rects)
> - or, make the default behavior not return a list of rects
> (return=False). default-on would be incorrect, imo.
> - many sources to many destinations would be complex, and there
> are no other pygame methods that operate like that (that i am aware
> of). so no for now, unless very easy to implement (probably not).
> 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?)
> I'm not so sure that multiprocessing is a way forward, because of the
> lock contention involved with the destination surface. Complex
> schemes to make lists of non-overlapping rects and delegating to
> workers smells np-complete to me. Threads/processes waiting around
> for a lock seems like it would ruin the benefits of parallelism. Who
> knows, however?
> This would be a great benefit for the built in sprite groups. Looking
> forward to seeing it implemented.
> On Tue, Mar 28, 2017 at 11:35 PM, René Dudfield <renesd@xxxxxxxxx>
> > 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:
> > - 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)