pygame-community / pygame-ce

🐍🎮 pygame - Community Edition is a FOSS Python library for multimedia applications (like games). Built on top of the excellent SDL library.
https://pyga.me
770 stars 120 forks source link

Use HasColorKey instead of GetColorKey in pgSurface_Blit #2835

Closed Starbuck5 closed 1 month ago

Starbuck5 commented 2 months ago

This routine doesn't use the value of GetColorKey, it just wants to know whether the surface has one.

Internally, this was setting a bunch of SDL errors ("surf doesn't have colorkey"-esque), which became much more expensive in SDL 2.29.3 because of a new logging feature.

Therefore lets replace it with HasColorKey (a newer function, the code was originally written before this existed). This fixes the performance regression here and even makes the performance slightly better than it was before, at least in my test scenario.

Credit to @itzpr3d4t0r for narrowing this down to SDL_GetColorKey

Relevant to #2821

Starbuck5 commented 2 months ago

Test script:

import random
import time

import pygame

random.seed(36)

width = 600
height = 400

screen = pygame.Surface((width, height))

def make_particle():
    p_surf = pygame.Surface((5,5))
    p_surf.fill((random.randint(0,255), random.randint(0,255), random.randint(0,255)))

    return (p_surf, (random.randint(0, width), random.randint(0, height)))

particles = [make_particle() for _ in range(1000000)]

start = time.time()
screen.fblits(particles)
print(time.time() - start)

Results:

Starbuck5 commented 2 months ago

An example of how the issue ( #2821 ) isn't fully fixed by this PR--

If you take the previous example and swap out the line defining p_surf for p_surf = pygame.Surface((5,5), pygame.SRCALPHA), to make it an alpha blit, there is still a performance problem.

On 2.4.1 it's 0.30 seconds, on main it's 1.60 seconds, and on this PR it's 0.63 seconds. So an improvement, but the SDL_GetColorKey in SoftBlitPyGame also needs to be re-evaluated

itzpr3d4t0r commented 2 months ago

An example of how the issue ( #2821 ) isn't fully fixed by this PR-- On 2.4.1 it's 0.30 seconds, on main it's 1.60 seconds, and on this PR it's 0.63 seconds. So an improvement, but the SDL_GetColorKey in SoftBlitPyGame also needs to be re-evaluated

About this, if SDL can do something about SDL_GetColorkey's perf we're good, otherwise could we implement our own function for that? I know SDL_Surface.map is private and it wouldn't be the best practice but what woud be the alternatives?