Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interface for _sdl2.video classes #3317

Merged
merged 12 commits into from
Feb 18, 2025
1 change: 1 addition & 0 deletions buildconfig/Setup.Android.SDL2.in
Original file line number Diff line number Diff line change
@@ -62,4 +62,5 @@ math src_c/math.c $(SDL) $(DEBUG)
pixelcopy src_c/pixelcopy.c $(SDL) $(DEBUG)
newbuffer src_c/newbuffer.c $(SDL) $(DEBUG)
window src_c/window.c $(SDL) $(DEBUG)
_render src_c/render.c $(SDL) $(DEBUG)
geometry src_c/geometry.c $(SDL) $(DEBUG)
1 change: 1 addition & 0 deletions buildconfig/Setup.Emscripten.SDL2.in
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@ rect src_c/void.c
rwobject src_c/void.c
system src_c/void.c
window src_c/void.c
_render src_c/void.c
geometry src_c/void.c

#_sdl2.controller src_c/_sdl2/controller.c $(SDL) $(DEBUG) -Isrc_c
1 change: 1 addition & 0 deletions buildconfig/Setup.SDL2.in
Original file line number Diff line number Diff line change
@@ -75,3 +75,4 @@ newbuffer src_c/newbuffer.c $(SDL) $(DEBUG)
system src_c/system.c $(SDL) $(DEBUG)
geometry src_c/geometry.c $(SDL) $(DEBUG)
window src_c/window.c $(SDL) $(DEBUG)
_render src_c/render.c $(SDL) $(DEBUG)
1 change: 1 addition & 0 deletions src_c/_pygame.h
Original file line number Diff line number Diff line change
@@ -616,6 +616,7 @@ typedef enum {
#define PYGAMEAPI_BASE_NUMSLOTS 30
#define PYGAMEAPI_EVENT_NUMSLOTS 10
#define PYGAMEAPI_WINDOW_NUMSLOTS 1
#define PYGAMEAPI_RENDER_NUMSLOTS 3
#define PYGAMEAPI_GEOMETRY_NUMSLOTS 2

#endif /* _PYGAME_INTERNAL_H */
46 changes: 46 additions & 0 deletions src_c/include/_pygame.h
Original file line number Diff line number Diff line change
@@ -520,6 +520,50 @@ typedef struct {
#define import_pygame_window() IMPORT_PYGAME_MODULE(window)
#endif

typedef struct pgTextureObject pgTextureObject;

/*
* Render module
*/
typedef struct {
PyObject_HEAD SDL_Renderer *renderer;
pgWindowObject *window;
pgTextureObject *target;
SDL_bool _is_borrowed;
} pgRendererObject;

struct pgTextureObject {
PyObject_HEAD SDL_Texture *texture;
pgRendererObject *renderer;
int width;
int height;
};

typedef struct {
PyObject_HEAD pgTextureObject *texture;
pgRectObject *srcrect;
pgColorObject *color;
float angle;
float alpha;
SDL_bool has_origin;
SDL_FPoint origin;
SDL_bool flip_x;
SDL_bool flip_y;
SDL_BlendMode blend_mode;
} pgImageObject;

#ifndef PYGAMEAPI_RENDER_INTERNAL
#define pgRenderer_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_render, 0))
#define pgTexture_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_render, 1))
#define pgImage_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_render, 2))
#define pgRenderer_Check(x) \
(PyObject_IsInstance((x), (PyObject *)&pgRender_Type))
#define pgTexture_Check(x) \
(PyObject_IsInstance((x), (PyObject *)&pgTexture_Type))
#define pgImage_Check(x) (PyObject_IsInstance((x), (PyObject *)&pgImage_Type))
#define import_pygame_render() IMPORT_PYGAME_MODULE(_render)
#endif

#define IMPORT_PYGAME_MODULE _IMPORT_PYGAME_MODULE

/*
@@ -539,6 +583,7 @@ PYGAMEAPI_DEFINE_SLOTS(pixelarray);
PYGAMEAPI_DEFINE_SLOTS(color);
PYGAMEAPI_DEFINE_SLOTS(math);
PYGAMEAPI_DEFINE_SLOTS(window);
PYGAMEAPI_DEFINE_SLOTS(_render);
PYGAMEAPI_DEFINE_SLOTS(geometry);
#else /* ~PYGAME_H */
PYGAMEAPI_EXTERN_SLOTS(base);
@@ -553,6 +598,7 @@ PYGAMEAPI_EXTERN_SLOTS(pixelarray);
PYGAMEAPI_EXTERN_SLOTS(color);
PYGAMEAPI_EXTERN_SLOTS(math);
PYGAMEAPI_EXTERN_SLOTS(window);
PYGAMEAPI_EXTERN_SLOTS(_render);
PYGAMEAPI_EXTERN_SLOTS(geometry);

#endif /* ~PYGAME_H */
12 changes: 12 additions & 0 deletions src_c/meson.build
Original file line number Diff line number Diff line change
@@ -316,6 +316,18 @@ window = py.extension_module(
subdir: pg,
)

# TODO: support SDL3
if sdl_api != 3
_render = py.extension_module(
'_render',
'render.c',
c_args: warnings_error,
dependencies: pg_base_deps,
install: true,
subdir: pg,
)
endif

# TODO: support SDL3
if sdl_api != 3
gfxdraw = py.extension_module(
126 changes: 126 additions & 0 deletions src_c/render.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#define PYGAMEAPI_RENDER_INTERNAL

#include "pygame.h"

#include "pgcompat.h"

#include "doc/sdl2_video_doc.h"

static PyTypeObject pgRenderer_Type;

static PyTypeObject pgTexture_Type;

static PyTypeObject pgImage_Type;

static PyMethodDef renderer_methods[] = {{NULL, NULL, 0, NULL}};

static PyGetSetDef renderer_getset[] = {{NULL, 0, NULL, NULL, NULL}};

static PyMethodDef texture_methods[] = {{NULL, NULL, 0, NULL}};

static PyGetSetDef texture_getset[] = {{NULL, 0, NULL, NULL, NULL}};

static PyMethodDef image_methods[] = {{NULL, NULL, 0, NULL}};

static PyGetSetDef image_getset[] = {{NULL, 0, NULL, NULL, NULL}};

static PyTypeObject pgRenderer_Type = {
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "pygame._render.Renderer",
.tp_basicsize = sizeof(pgRendererObject),
//.tp_dealloc = (destructor)renderer_dealloc,
.tp_doc = DOC_SDL2_VIDEO_RENDERER, .tp_methods = renderer_methods,
//.tp_init = (initproc)renderer_init,
.tp_new = PyType_GenericNew, .tp_getset = renderer_getset};

static PyTypeObject pgTexture_Type = {
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "pygame._render.Texture",
.tp_basicsize = sizeof(pgTextureObject),
//.tp_dealloc = (destructor)texture_dealloc,
.tp_doc = DOC_SDL2_VIDEO_TEXTURE, .tp_methods = texture_methods,
//.tp_init = (initproc)texture_init,
.tp_new = PyType_GenericNew, .tp_getset = texture_getset};

static PyTypeObject pgImage_Type = {
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "pygame._render.Image",
.tp_basicsize = sizeof(pgImageObject),
//.tp_dealloc = (destructor)image_dealloc,
.tp_doc = DOC_SDL2_VIDEO_IMAGE, .tp_methods = image_methods,
//.tp_init = (initproc)image_init,
.tp_new = PyType_GenericNew, .tp_getset = image_getset};

static PyMethodDef _render_methods[] = {{NULL, NULL, 0, NULL}};

MODINIT_DEFINE(_render)
{
PyObject *module, *apiobj;
static void *c_api[PYGAMEAPI_RENDER_NUMSLOTS];

static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
"_render",
"docs_needed",
-1,
_render_methods,
NULL,
NULL,
NULL,
NULL};

/* imported needed apis; Do this first so if there is an error
the module is not loaded.
*/
import_pygame_base();
if (PyErr_Occurred()) {
return NULL;
}

if (PyType_Ready(&pgRenderer_Type) < 0) {
return NULL;
}

if (PyType_Ready(&pgTexture_Type) < 0) {
return NULL;
}

if (PyType_Ready(&pgImage_Type) < 0) {
return NULL;
}

/* create the module */
module = PyModule_Create(&_module);
if (module == 0) {
return NULL;
}

Py_INCREF(&pgRenderer_Type);
if (PyModule_AddObject(module, "Renderer", (PyObject *)&pgRenderer_Type)) {
Py_DECREF(&pgRenderer_Type);
Py_DECREF(module);
return NULL;
}

Py_INCREF(&pgTexture_Type);
if (PyModule_AddObject(module, "Texture", (PyObject *)&pgTexture_Type)) {
Py_DECREF(&pgTexture_Type);
Py_DECREF(module);
return NULL;
}

Py_INCREF(&pgImage_Type);
if (PyModule_AddObject(module, "Image", (PyObject *)&pgImage_Type)) {
Py_DECREF(&pgImage_Type);
Py_DECREF(module);
return NULL;
}

c_api[0] = &pgRenderer_Type;
c_api[1] = &pgTexture_Type;
c_api[2] = &pgImage_Type;
apiobj = encapsulate_api(c_api, "_render");
if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) {
Py_XDECREF(apiobj);
Py_DECREF(module);
return NULL;
}

return module;
}
6 changes: 6 additions & 0 deletions src_c/static.c
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
#define PYGAMEAPI_BASE_INTERNAL
#define PYGAMEAPI_SURFACE_INTERNAL
#define PYGAMEAPI_WINDOW_INTERNAL
#define PYGAMEAPI_RENDER_INTERNAL

#define pgSurface_New(surface) (pgSurfaceObject *)pgSurface_New2((surface), 1)
#define pgSurface_NewNoOwn(surface) \
@@ -187,6 +188,9 @@ PyInit_pixelarray(void);
PyMODINIT_FUNC
PyInit_window(void);

PyMODINIT_FUNC
PyInit__render(void);

// pygame_static module

void
@@ -320,6 +324,7 @@ PyInit_pygame_static()
load_submodule("pygame.mixer", PyInit_mixer_music(), "music");

load_submodule("pygame", PyInit_window(), "window");
load_submodule("pygame", PyInit__render(), "_render");

load_submodule("pygame", PyInit_pixelarray(), "pixelarray");

@@ -364,6 +369,7 @@ PyInit_pygame_static()
#include "simd_blitters_sse2.c"

#include "window.c"
#include "render.c"

#undef pgVidInfo_Type
#undef pgVidInfo_New