Skip to content

Commit

Permalink
Merge pull request #2933 from Starbuck5/rwobject-fixes-sdl3
Browse files Browse the repository at this point in the history
Fixes for rwobject (now iostream) SDL3
  • Loading branch information
ankith26 authored Oct 6, 2024
2 parents e2704e6 + 7202d48 commit f3f112a
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 9 deletions.
3 changes: 1 addition & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ sdl_ttf = '@0@_ttf'.format(sdl)
sdl_image = '@0@_image'.format(sdl)

if sdl_api == 3
add_global_arguments('-DPG_SDL3=1', language: 'c')
add_global_arguments('-DSDL_ENABLE_OLD_NAMES=1', language: 'c')
add_global_arguments('-DPG_SDL3=1', '-DSDL_ENABLE_OLD_NAMES=1', language: 'c')
endif

pg_inc_dirs = []
Expand Down
8 changes: 6 additions & 2 deletions src_c/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,15 +1174,19 @@ font_init(PyFontObject *self, PyObject *args, PyObject *kwds)
if (fontsize <= 1)
fontsize = 1;

if (rw->size(rw) <= 0) {
if (SDL_RWsize(rw) <= 0) {
PyErr_Format(PyExc_ValueError,
"Font file object has an invalid file size: %lld",
rw->size(rw));
SDL_RWsize(rw));
goto error;
}

Py_BEGIN_ALLOW_THREADS;
#if SDL_VERSION_ATLEAST(3, 0, 0)
font = TTF_OpenFontIO(rw, 1, fontsize);
#else
font = TTF_OpenFontRW(rw, 1, fontsize);
#endif
Py_END_ALLOW_THREADS;

Py_DECREF(obj);
Expand Down
22 changes: 21 additions & 1 deletion src_c/imageext.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,18 @@ image_load_ext(PyObject *self, PyObject *arg, PyObject *kwarg)
SDL_UnlockMutex(_pg_img_mutex);
*/

#if SDL_VERSION_ATLEAST(3, 0, 0)
surf = IMG_LoadTyped_IO(rw, 1, type);
#else
surf = IMG_LoadTyped_RW(rw, 1, type);
#endif
Py_END_ALLOW_THREADS;
#else /* ~WITH_THREAD */
#else /* ~WITH_THREAD */
#if SDL_VERSION_ATLEAST(3, 0, 0)
surf = IMG_LoadTyped_IO(rw, 1, type);
#else
surf = IMG_LoadTyped_RW(rw, 1, type);
#endif
#endif /* ~WITH_THREAD */

if (ext) {
Expand Down Expand Up @@ -166,7 +174,11 @@ imageext_load_sized_svg(PyObject *self, PyObject *arg, PyObject *kwargs)
}

Py_BEGIN_ALLOW_THREADS;
#if SDL_VERSION_ATLEAST(3, 0, 0)
surf = IMG_LoadSizedSVG_IO(rw, width, height);
#else
surf = IMG_LoadSizedSVG_RW(rw, width, height);
#endif
SDL_RWclose(rw);
Py_END_ALLOW_THREADS;
if (surf == NULL) {
Expand Down Expand Up @@ -231,7 +243,11 @@ image_save_ext(PyObject *self, PyObject *arg, PyObject *kwarg)
char *ext = iext_find_extension(name);
if (!strcasecmp(ext, "jpeg") || !strcasecmp(ext, "jpg")) {
if (rw != NULL) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
result = IMG_SaveJPG_IO(surf, rw, 0, JPEG_QUALITY);
#else
result = IMG_SaveJPG_RW(surf, rw, 0, JPEG_QUALITY);
#endif
}
else {
result = IMG_SaveJPG(surf, name, JPEG_QUALITY);
Expand All @@ -240,7 +256,11 @@ image_save_ext(PyObject *self, PyObject *arg, PyObject *kwarg)
else if (!strcasecmp(ext, "png")) {
/*Py_BEGIN_ALLOW_THREADS; */
if (rw != NULL) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
result = IMG_SavePNG_IO(surf, rw, 0);
#else
result = IMG_SavePNG_RW(surf, rw, 0);
#endif
}
else {
result = IMG_SavePNG(surf, name);
Expand Down
3 changes: 0 additions & 3 deletions src_c/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ rect = py.extension_module(
subdir: pg,
)

# TODO: support SDL3
if sdl_api != 3
rwobject = py.extension_module(
'rwobject',
'rwobject.c',
Expand All @@ -103,7 +101,6 @@ rwobject = py.extension_module(
install: true,
subdir: pg,
)
endif

# TODO: support SDL3
if sdl_api != 3
Expand Down
4 changes: 4 additions & 0 deletions src_c/mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1875,7 +1875,11 @@ sound_init(PyObject *self, PyObject *arg, PyObject *kwarg)
return -1;
}
Py_BEGIN_ALLOW_THREADS;
#if SDL_VERSION_ATLEAST(3, 0, 0)
chunk = Mix_LoadWAV_IO(rw, 1);
#else
chunk = Mix_LoadWAV_RW(rw, 1);
#endif
Py_END_ALLOW_THREADS;
if (chunk == NULL) {
PyErr_SetString(pgExc_SDLError, SDL_GetError());
Expand Down
4 changes: 4 additions & 0 deletions src_c/music.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,11 @@ _load_music(PyObject *obj, char *namehint)
}

Py_BEGIN_ALLOW_THREADS;
#if SDL_VERSION_ATLEAST(3, 0, 0)
new_music = Mix_LoadMUSType_IO(rw, _get_type_from_hint(type), SDL_TRUE);
#else
new_music = Mix_LoadMUSType_RW(rw, _get_type_from_hint(type), SDL_TRUE);
#endif
Py_END_ALLOW_THREADS;

if (ext) {
Expand Down
113 changes: 112 additions & 1 deletion src_c/rwobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ static const char pg_default_errors[] = "backslashreplace";

static PyObject *os_module = NULL;

#if SDL_VERSION_ATLEAST(3, 0, 0)
static Sint64
_pg_rw_size(void *);
static Sint64
_pg_rw_seek(void *, Sint64, SDL_IOWhence);
static size_t
_pg_rw_read(void *, void *, size_t, SDL_IOStatus *);
static size_t
_pg_rw_write(void *, const void *, size_t, SDL_IOStatus *);
static bool
_pg_rw_close(void *);
#else
static Sint64
_pg_rw_size(SDL_RWops *);
static Sint64
Expand All @@ -56,6 +68,7 @@ static size_t
_pg_rw_write(SDL_RWops *, const void *, size_t, size_t);
static int
_pg_rw_close(SDL_RWops *);
#endif

/* Converter function used by PyArg_ParseTupleAndKeywords with the "O&" format.
*
Expand Down Expand Up @@ -291,13 +304,31 @@ pg_EncodeFilePath(PyObject *obj, PyObject *eclass)
static int
pgRWops_IsFileObject(SDL_RWops *rw)
{
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_PropertiesID props = SDL_GetIOProperties(rw);
if (!props) {
// pgRWops_IsFileObject doesn't have any error checking facility
// so when in doubt let's say it isn't a file object.
return 0;
}
return SDL_GetBooleanProperty(props, "_pygame_is_file_object", 0);
#else
return rw->close == _pg_rw_close;
#endif
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
static Sint64
_pg_rw_size(void *userdata)
{
pgRWHelper *helper = (pgRWHelper *)userdata;
#else
static Sint64
_pg_rw_size(SDL_RWops *context)
{
pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1;
#endif

PyObject *pos = NULL;
PyObject *tmp = NULL;
Sint64 size;
Expand Down Expand Up @@ -361,10 +392,19 @@ _pg_rw_size(SDL_RWops *context)
return retval;
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
static size_t
_pg_rw_write(void *userdata, const void *ptr, size_t size,
SDL_IOStatus *status)
{
pgRWHelper *helper = (pgRWHelper *)userdata;
size_t num = 1;
#else
static size_t
_pg_rw_write(SDL_RWops *context, const void *ptr, size_t size, size_t num)
{
pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1;
#endif
PyObject *result;
size_t retval;

Expand All @@ -382,26 +422,42 @@ _pg_rw_write(SDL_RWops *context, const void *ptr, size_t size, size_t num)
}

Py_DECREF(result);
#if SDL_VERSION_ATLEAST(3, 0, 0)
retval = size;
#else
retval = num;
#endif

end:
PyGILState_Release(state);
return retval;
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
static bool
_pg_rw_close(void *userdata)
{
pgRWHelper *helper = (pgRWHelper *)userdata;
bool retval = true;
#else
static int
_pg_rw_close(SDL_RWops *context)
{
pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1;
PyObject *result;
int retval = 0;
#endif
PyObject *result;
PyGILState_STATE state = PyGILState_Ensure();

if (helper->close) {
result = PyObject_CallNoArgs(helper->close);
if (!result) {
PyErr_Print();
#if SDL_VERSION_ATLEAST(3, 0, 0)
retval = false;
#else
retval = -1;
#endif
}
Py_XDECREF(result);
}
Expand All @@ -414,7 +470,9 @@ _pg_rw_close(SDL_RWops *context)

PyMem_Free(helper);
PyGILState_Release(state);
#if !SDL_VERSION_ATLEAST(3, 0, 0)
SDL_FreeRW(context);
#endif
return retval;
}

Expand All @@ -437,6 +495,37 @@ pgRWops_FromFileObject(PyObject *obj)
return NULL;
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_IOStreamInterface iface;
iface.size = _pg_rw_size;
iface.seek = _pg_rw_seek;
iface.read = _pg_rw_read;
iface.write = _pg_rw_write;
iface.close = _pg_rw_close;

// TODO: These should raise SDLError probably?
// rwobject.c hasn't required pygame.base before (the source of SDLError)
// so omitting that for now.

rw = SDL_OpenIO(&iface, helper);
if (rw == NULL) {
iface.close(helper);
PyMem_Free(helper);
return (SDL_RWops *)RAISE(PyExc_IOError, SDL_GetError());
}

SDL_PropertiesID props = SDL_GetIOProperties(rw);
if (!props) {
PyMem_Free(helper);
return (SDL_RWops *)RAISE(PyExc_IOError, SDL_GetError());
}

if (!SDL_SetBooleanProperty(props, "_pygame_is_file_object", 1)) {
PyMem_Free(helper);
return (SDL_RWops *)RAISE(PyExc_IOError, SDL_GetError());
}

#else
rw = SDL_AllocRW();
if (rw == NULL) {
PyMem_Free(helper);
Expand All @@ -450,14 +539,22 @@ pgRWops_FromFileObject(PyObject *obj)
rw->read = _pg_rw_read;
rw->write = _pg_rw_write;
rw->close = _pg_rw_close;
#endif

return rw;
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
static Sint64
_pg_rw_seek(void *userdata, Sint64 offset, SDL_IOWhence whence)
{
pgRWHelper *helper = (pgRWHelper *)userdata;
#else
static Sint64
_pg_rw_seek(SDL_RWops *context, Sint64 offset, int whence)
{
pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1;
#endif
PyObject *result;
Sint64 retval;

Expand Down Expand Up @@ -498,10 +595,18 @@ _pg_rw_seek(SDL_RWops *context, Sint64 offset, int whence)
return retval;
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
static size_t
_pg_rw_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
{
pgRWHelper *helper = (pgRWHelper *)userdata;
size_t maxnum = 1;
#else
static size_t
_pg_rw_read(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
{
pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1;
#endif
PyObject *result;
Py_ssize_t retval;

Expand All @@ -527,7 +632,9 @@ _pg_rw_read(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
retval = PyBytes_GET_SIZE(result);
if (retval) {
memcpy(ptr, PyBytes_AsString(result), retval);
#if !SDL_VERSION_ATLEAST(3, 0, 0)
retval /= size;
#endif
}

Py_DECREF(result);
Expand Down Expand Up @@ -581,7 +688,11 @@ _rwops_from_pystr(PyObject *obj, char **extptr)
/* If out of memory, decref oencoded to be safe, and try
* to close out `rw` as well. */
Py_DECREF(oencoded);
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (!SDL_RWclose(rw)) {
#else
if (SDL_RWclose(rw) < 0) {
#endif
PyErr_SetString(PyExc_IOError, SDL_GetError());
}
return (SDL_RWops *)PyErr_NoMemory();
Expand Down

0 comments on commit f3f112a

Please sign in to comment.