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

Implement display.gl_get_proc #3285

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions buildconfig/stubs/pygame/display.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections.abc import Iterable
from ctypes import _FuncPointer
from typing import Optional, Union, overload, Literal
from typing_extensions import deprecated # added in 3.13

Expand Down Expand Up @@ -70,6 +71,7 @@ def mode_ok(
) -> int: ...
def gl_get_attribute(flag: int, /) -> int: ...
def gl_set_attribute(flag: int, value: int, /) -> None: ...
def gl_get_proc(proc_name: str) -> _FuncPointer: ...
def get_active() -> bool: ...
def iconify() -> bool: ...
def toggle_fullscreen() -> int: ...
Expand Down
7 changes: 7 additions & 0 deletions docs/reST/ref/display.rst
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,13 @@ required).

.. ## pygame.display.gl_set_attribute ##
.. function:: gl_get_proc

| :sl:`Get an OpenGL function by name`
| :sg:`gl_get_proc(proc_name) -> ctypes._FuncPointer`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is an uncommon function it could be explained with a bit more detail, for example mentioning that it will try to import ctypes if it is not imported, the fact that it can fail and raise errors, and if it's relevant roughly how to use the return value with an embedded example.

.. # pygame.display.gl_get_proc ##
.. function:: get_active

| :sl:`Returns True when the display is active on the screen`
Expand Down
65 changes: 65 additions & 0 deletions src_c/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2938,6 +2938,69 @@ pg_message_box(PyObject *self, PyObject *arg, PyObject *kwargs)
return NULL;
}

static PyObject *ctypes_functype = NULL;

static PyObject *
pg_gl_get_proc(PyObject *self, PyObject *arg)
{
if (!PyUnicode_Check(arg)) {
return RAISE(PyExc_TypeError, "'proc_name' should be a string");
}
const char *proc_name = PyUnicode_AsUTF8(arg);
if (!proc_name) {
return NULL;
}

#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_FunctionPointer proc_addr;
#else
void *proc_addr;
#endif
proc_addr = SDL_GL_GetProcAddress(proc_name);
if (!proc_addr) {
PyErr_Format(pgExc_SDLError, "Unable to get OpenGL function '%s'",
proc_name);
return NULL;
}
PyObject *proc_addr_obj = PyLong_FromVoidPtr(proc_addr);
if (!proc_addr_obj) {
return NULL;
}

// load ctypes_functype if it's NULL
if (!ctypes_functype) {
PyObject *ctypes_module = PyImport_ImportModule("ctypes");
if (!ctypes_module) {
return NULL;
}

PyObject *ctypes_functype_factory;
#if defined(_WIN32)
// gl proc need to be called with WINFUNCTYPE (stdcall) on win32
ctypes_functype_factory =
PyObject_GetAttrString(ctypes_module, "WINFUNCTYPE");
#else
ctypes_functype_factory =
PyObject_GetAttrString(ctypes_module, "CFUNCTYPE");
#endif
Py_DECREF(ctypes_module);
if (!ctypes_functype_factory) {
return NULL;
}

ctypes_functype =
PyObject_CallOneArg(ctypes_functype_factory, Py_None);
Py_DECREF(ctypes_functype_factory);
if (!ctypes_functype) {
return NULL;
}
}

PyObject *retv = PyObject_CallOneArg(ctypes_functype, proc_addr_obj);
Py_DECREF(proc_addr_obj);
return retv;
}

static PyMethodDef _pg_display_methods[] = {
{"init", (PyCFunction)pg_display_init, METH_NOARGS, DOC_DISPLAY_INIT},
{"quit", (PyCFunction)pg_display_quit, METH_NOARGS, DOC_DISPLAY_QUIT},
Expand Down Expand Up @@ -3015,6 +3078,8 @@ static PyMethodDef _pg_display_methods[] = {
METH_VARARGS | METH_KEYWORDS, DOC_DISPLAY_SETALLOWSCREENSAVER},
{"message_box", (PyCFunction)pg_message_box, METH_VARARGS | METH_KEYWORDS,
DOC_DISPLAY_MESSAGEBOX},
{"gl_get_proc", (PyCFunction)pg_gl_get_proc, METH_O,
DOC_DISPLAY_GLGETPROC},
{NULL, NULL, 0, NULL}};

#ifndef PYPY_VERSION
Expand Down
1 change: 1 addition & 0 deletions src_c/doc/display_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define DOC_DISPLAY_MODEOK "mode_ok(size, flags=0, depth=0, display=0) -> depth\nPick the best color depth for a display mode"
#define DOC_DISPLAY_GLGETATTRIBUTE "gl_get_attribute(flag, /) -> value\nGet the value for an OpenGL flag for the current display"
#define DOC_DISPLAY_GLSETATTRIBUTE "gl_set_attribute(flag, value, /) -> None\nRequest an OpenGL display attribute for the display mode"
#define DOC_DISPLAY_GLGETPROC "gl_get_proc(proc_name) -> ctypes._FuncPointer\nGet an OpenGL function by name"
#define DOC_DISPLAY_GETACTIVE "get_active() -> bool\nReturns True when the display is active on the screen"
#define DOC_DISPLAY_ICONIFY "iconify() -> bool\nIconify the display surface"
#define DOC_DISPLAY_TOGGLEFULLSCREEN "toggle_fullscreen() -> int\nSwitch between fullscreen and windowed displays"
Expand Down
Loading