Skip to content

Commit 43e4597

Browse files
committed
Fixed merge conflict with multiphase init
2 parents 695f04c + 2d4f65f commit 43e4597

File tree

3 files changed

+86
-58
lines changed

3 files changed

+86
-58
lines changed

examples/multithreaded_surface.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
import pygame
2-
import threading
31
import random
4-
2+
import sys
3+
import threading
54
from time import perf_counter
65

7-
start = perf_counter()
6+
import pygame
87

98
pygame.init()
109

10+
print(f"{sys._is_gil_enabled() = }")
11+
1112
WIDTH, HEIGHT = 100, 100
1213
NUM_THREADS = 10
1314
surface = pygame.Surface((WIDTH, HEIGHT))
1415
surface.fill("black")
1516

16-
LERP_OFFSET = 0.001
17+
LERP_OFFSET = 0.0001
1718

1819

1920
def get_random_color() -> pygame.Color:
@@ -47,6 +48,7 @@ def multithreaded_func(
4748
for i in range(WIDTH * HEIGHT // NUM_THREADS)
4849
}
4950

51+
start = perf_counter()
5052
for batch in batches.values():
5153
threads: list[threading.Thread] = []
5254
for pixel, color in batch:
@@ -58,13 +60,26 @@ def multithreaded_func(
5860

5961
while any([t.is_alive() for t in threads]):
6062
continue
63+
end = perf_counter()
6164

6265
pygame.image.save(pygame.transform.scale_by(surface, 10), "out.png")
6366

64-
end = perf_counter()
65-
6667
print(f"time taken: {end - start}")
6768

6869
for pixel, color in zip(pixels, colors):
6970
surface.set_at(pixel, color)
7071
pygame.image.save(pygame.transform.scale_by(surface, 10), "comparison.png")
72+
73+
import numpy
74+
75+
threaded_surf = pygame.image.load("out.png")
76+
compare_surf = pygame.image.load("comparison.png")
77+
78+
threaded_arr = pygame.surfarray.array3d(threaded_surf)
79+
compare_arr = pygame.surfarray.array3d(compare_surf)
80+
81+
threaded_alpha = pygame.surfarray.array_alpha(threaded_surf)
82+
compare_alpha = pygame.surfarray.array_alpha(compare_surf)
83+
84+
numpy.testing.assert_array_equal(threaded_arr, compare_arr)
85+
numpy.testing.assert_array_equal(threaded_alpha, compare_alpha)

src_c/include/_pygame.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,10 +670,15 @@ PYGAMEAPI_EXTERN_SLOTS(geometry);
670670
Py_DECREF(module); \
671671
return NULL; \
672672
} \
673-
printf("%s was compiled with GIL disabled\n", name);
674-
#else
673+
printf("%s was compiled with GIL disabled (single)\n", name);
674+
#define DISABLE_GIL_MULTIPHASE_INITIALIZATION(name) \
675+
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
676+
677+
#else // PY_GIL_DISABLED is not defined
675678
#define DISABLE_GIL_SINGLE_INITIALIZATION(module, name) \
676-
printf("%s was compiled with GIL enabled\n", name);
679+
printf("%s was compiled with GIL disabled (single)\n", name);
680+
#define DISABLE_GIL_MULTIPHASE_INITIALIZATION(name) \
681+
{Py_mod_gil, Py_MOD_GIL_USED},
677682
#endif
678683

679684
static PG_INLINE PyObject *

src_c/surface.c

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ typedef enum {
5252
} SurfViewKind;
5353

5454
/* To avoid problems with non-const Py_buffer format field */
55-
static char FormatUint8[] = "B";
56-
static char FormatUint16[] = "=H";
57-
static char FormatUint24[] = "3x";
58-
static char FormatUint32[] = "=I";
55+
#define FormatUint8 "B"
56+
#define FormatUint16 "=H"
57+
#define FormatUint24 "3x"
58+
#define FormatUint32 "=I"
5959

6060
typedef struct pg_bufferinternal_s {
6161
PyObject *consumer_ref; /* A weak reference to a bufferproxy object */
@@ -4623,17 +4623,64 @@ pgSurface_Blit(pgSurfaceObject *dstobj, pgSurfaceObject *srcobj,
46234623

46244624
static PyMethodDef _surface_methods[] = {{NULL, NULL, 0, NULL}};
46254625

4626-
MODINIT_DEFINE(surface)
4626+
int
4627+
exec_surface(PyObject *module)
46274628
{
4628-
PyObject *module, *apiobj;
4629+
PyObject *apiobj;
46294630
static void *c_api[PYGAMEAPI_SURFACE_NUMSLOTS];
46304631

4632+
if (pg_warn_simd_at_runtime_but_uncompiled() < 0) {
4633+
return -1;
4634+
}
4635+
4636+
if (PyModule_AddObjectRef(module, "SurfaceType",
4637+
(PyObject *)&pgSurface_Type)) {
4638+
return -1;
4639+
}
4640+
4641+
if (PyModule_AddObjectRef(module, "Surface",
4642+
(PyObject *)&pgSurface_Type)) {
4643+
return -1;
4644+
}
4645+
4646+
/* export the c api */
4647+
c_api[0] = &pgSurface_Type;
4648+
c_api[1] = pgSurface_New2;
4649+
c_api[2] = pgSurface_Blit;
4650+
c_api[3] = pgSurface_SetSurface;
4651+
apiobj = encapsulate_api(c_api, "surface");
4652+
if (PyModule_AddObjectRef(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) {
4653+
Py_XDECREF(apiobj);
4654+
return -1;
4655+
}
4656+
4657+
if (PyModule_AddObjectRef(module, "_dict", pgSurface_Type.tp_dict)) {
4658+
return -1;
4659+
}
4660+
4661+
return 0;
4662+
}
4663+
4664+
MODINIT_DEFINE(surface)
4665+
{
4666+
static PyModuleDef_Slot surf_slots[] = {
4667+
{Py_mod_exec, &exec_surface},
4668+
#if PY_VERSION_HEX >= 0x030c0000
4669+
{Py_mod_multiple_interpreters,
4670+
Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, // TODO: see if this can
4671+
// be supported later
4672+
#endif
4673+
#if PY_VERSION_HEX >= 0x030d0000
4674+
DISABLE_GIL_MULTIPHASE_INITIALIZATION("surface")
4675+
#endif
4676+
{0, NULL}};
4677+
46314678
static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
46324679
"surface",
46334680
DOC_SURFACE,
4634-
-1,
4681+
0,
46354682
_surface_methods,
4636-
NULL,
4683+
surf_slots,
46374684
NULL,
46384685
NULL,
46394686
NULL};
@@ -4667,44 +4714,5 @@ MODINIT_DEFINE(surface)
46674714
return NULL;
46684715
}
46694716

4670-
/* create the module */
4671-
module = PyModule_Create(&_module);
4672-
if (module == NULL) {
4673-
return NULL;
4674-
}
4675-
4676-
DISABLE_GIL_SINGLE_INITIALIZATION(module, _module.m_name)
4677-
4678-
if (pg_warn_simd_at_runtime_but_uncompiled() < 0) {
4679-
Py_DECREF(module);
4680-
return NULL;
4681-
}
4682-
if (PyModule_AddObjectRef(module, "SurfaceType",
4683-
(PyObject *)&pgSurface_Type)) {
4684-
Py_DECREF(module);
4685-
return NULL;
4686-
}
4687-
4688-
if (PyModule_AddObjectRef(module, "Surface",
4689-
(PyObject *)&pgSurface_Type)) {
4690-
Py_DECREF(module);
4691-
return NULL;
4692-
}
4693-
4694-
/* export the c api */
4695-
c_api[0] = &pgSurface_Type;
4696-
c_api[1] = pgSurface_New2;
4697-
c_api[2] = pgSurface_Blit;
4698-
c_api[3] = pgSurface_SetSurface;
4699-
apiobj = encapsulate_api(c_api, "surface");
4700-
if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) {
4701-
Py_XDECREF(apiobj);
4702-
Py_DECREF(module);
4703-
return NULL;
4704-
}
4705-
if (PyModule_AddObjectRef(module, "_dict", pgSurface_Type.tp_dict)) {
4706-
Py_DECREF(module);
4707-
return NULL;
4708-
}
4709-
return module;
4717+
return PyModuleDef_Init(&_module);
47104718
}

0 commit comments

Comments
 (0)