Skip to content
Open
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
274 changes: 252 additions & 22 deletions buildconfig/stubs/pygame/_render.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
"""Experimental pygame module porting the SDL render video system

The SDL render video system supports both software and GPU-accelerated
rendering through the Renderer, Texture and Image objects.

.. versionadded:: 2.5.4
"""

# render.rst contents for the future
"""
.. include:: common.txt

:mod:`pygame._render`
=====================

.. warning::
This module isn't ready for prime time yet, it's still in development.
These docs are primarily meant to help the pygame developers and
super-early adopters who are in communication with the developers.
This API will change.

Also, this module is a C implementation of most of the features of the
sdl2_video module. It is currently incomplete.

.. autopgmodule:: pygame._render
:members:

"""

from collections.abc import Iterable
from typing import Any, Optional, Protocol, Union, final

Expand All @@ -15,6 +44,35 @@ class _DrawableClass(Protocol):

@final
class Renderer:
"""Object wrapping a 2D rendering context for a window

:class:`Renderer` objects provide a cross-platform API for rendering 2D
graphics onto a :class:`Window`, by using either Metal (macOS), OpenGL
(macOS, Windows, Linux) or Direct3D (Windows) rendering drivers, depending
on what is set or is available on a system during their creation.

They can be used to draw both :class:`Texture` objects and simple points,
lines and rectangles (which are colored based on :attr:`Renderer.draw_color`).

If configured correctly and supported by an underlying rendering driver, Renderer
objects can have a :class:`Texture` object temporarily set as a target texture
(the Texture object must have been created with target texture usage support),
which allows those textures to be drawn onto.

To present drawn content onto the window, :meth:`Renderer.present` should be
called. :meth:`Renderer.clear` should be called to clear any drawn content
with the set Renderer draw color.

When things are drawn onto Renderer objects, an internal batching system is
used by default to batch those "draw calls" together, to have all of them be
processed in one go when :meth:`Renderer.present` is called. This is unlike
:class:`pygame.Surface` objects, on which modifications via blitting occur
immediately, but lends well to the behavior of GPUs, as draw calls can be
expensive on lower-end models.

.. versionadded:: 2.5.4
"""

def __init__(
self,
window: Window,
Expand All @@ -29,53 +87,222 @@ class Renderer:
dest: Optional[RectLike] = None,
area: Optional[RectLike] = None,
special_flags: int = 0,
) -> Rect: ...
def clear(self) -> None: ...
def draw_line(self, p1: Point, p2: Point) -> None: ...
def draw_point(self, point: Point) -> None: ...
def draw_quad(self, p1: Point, p2: Point, p3: Point, p4: Point) -> None: ...
def draw_rect(self, rect: RectLike) -> None: ...
def draw_triangle(self, p1: Point, p2: Point, p3: Point) -> None: ...
def fill_quad(self, p1: Point, p2: Point, p3: Point, p4: Point) -> None: ...
def fill_rect(self, rect: RectLike) -> None: ...
def fill_triangle(self, p1: Point, p2: Point, p3: Point) -> None: ...
def get_viewport(self) -> Rect: ...
) -> Rect:
"""Draw textures using a Surface-like API

For compatibility purposes. Draws :class:`Texture` objects onto the
Renderer using a method signature similar to :meth:`pygame.Surface.blit`.

:param source: A :class:`Texture` or :class:`Image` to draw.
:param dest: The drawing destination on the rendering target.
:param area: The portion of the source texture or image to draw from.
:param special_flags: have no effect at this moment.

.. note:: Textures created by different Renderers cannot shared with each other!

Comment on lines +101 to +102
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Grammar: “cannot shared” → “cannot be shared”.

Minor but visible in the public docs.

Apply this diff:

-        .. note:: Textures created by different Renderers cannot shared with each other!
+        .. note:: Textures created by different Renderers cannot be shared with each other!
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.. note:: Textures created by different Renderers cannot shared with each other!
.. note:: Textures created by different Renderers cannot be shared with each other!
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/_render.pyi around lines 102 to 103, fix the grammar
in the docstring by changing "cannot shared" to "cannot be shared"; update the
note line to read: "Textures created by different Renderers cannot be shared
with each other!" and save the file.

.. versionadded:: 2.5.4
"""

def clear(self) -> None:
"""Clear the current rendering target with the drawing color"""

def draw_line(self, p1: Point, p2: Point) -> None:
"""Draw a line

:param p1: The line start point.
:param p2: The line end point.

.. versionadded:: 2.5.4
"""

def draw_point(self, point: Point) -> None:
"""Draw a point

:param point: The point's coordinates.

.. versionadded:: 2.5.4
"""

def draw_quad(self, p1: Point, p2: Point, p3: Point, p4: Point) -> None:
"""Draw a quad outline

:param p1: The first quad point.
:param p2: The second quad point.
:param p2: The third quad point.
:param p2: The fourth quad point.

Comment on lines +129 to +133
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parameter names in draw_quad docs (p3/p4 mislabelled).

Parameters are repeated as p2 for p3 and p4.

Apply this diff:

-        :param p2: The third quad point.
-        :param p2: The fourth quad point.
+        :param p3: The third quad point.
+        :param p4: The fourth quad point.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:param p1: The first quad point.
:param p2: The second quad point.
:param p2: The third quad point.
:param p2: The fourth quad point.
:param p1: The first quad point.
:param p2: The second quad point.
:param p3: The third quad point.
:param p4: The fourth quad point.
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/_render.pyi around lines 130 to 134, the docstring
parameter labels for the third and fourth quad points are incorrectly repeated
as `p2`; update the parameter names so they read `:param p3: The third quad
point.` and `:param p4: The fourth quad point.` to match the actual parameters
and fix the documentation.

.. versionadded:: 2.5.4
"""

def draw_rect(self, rect: RectLike) -> None:
"""Draw a rectangle outline

:param rect: The :class:`pygame.Rect`-like rectangle to draw.

.. versionadded:: 2.5.4
"""

def draw_triangle(self, p1: Point, p2: Point, p3: Point) -> None:
"""Draw a triangle outline

:param p1: The first triangle point.
:param p2: The second triangle point.
:param p2: The third triangle point.

Comment on lines +148 to +151
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parameter name in draw_triangle docs (p3 mislabelled).

Third point is documented as p2.

Apply this diff:

-        :param p2: The third triangle point.
+        :param p3: The third triangle point.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:param p1: The first triangle point.
:param p2: The second triangle point.
:param p2: The third triangle point.
:param p1: The first triangle point.
:param p2: The second triangle point.
:param p3: The third triangle point.
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/_render.pyi around lines 149 to 152, the docstring
for draw_triangle incorrectly documents the third triangle point as ":param p2:"
instead of ":param p3:". Update the third parameter documentation line to read
":param p3: The third triangle point." (ensure only the parameter name is
corrected and formatting preserved).

.. versionadded:: 2.5.4
"""

def fill_quad(self, p1: Point, p2: Point, p3: Point, p4: Point) -> None:
"""Draw a filled quad

:param p1: The first quad point.
:param p2: The second quad point.
:param p2: The third quad point.
:param p2: The fourth quad point.

Comment on lines +158 to +162
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parameter names in fill_quad docs (p3/p4 mislabelled).

Same issue as draw_quad.

Apply this diff:

-        :param p2: The third quad point.
-        :param p2: The fourth quad point.
+        :param p3: The third quad point.
+        :param p4: The fourth quad point.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:param p1: The first quad point.
:param p2: The second quad point.
:param p2: The third quad point.
:param p2: The fourth quad point.
:param p1: The first quad point.
:param p2: The second quad point.
:param p3: The third quad point.
:param p4: The fourth quad point.
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/_render.pyi around lines 159 to 163, the docstring
for fill_quad mislabels the third and fourth quad point parameters as p2; update
the parameter names so they read ":param p1: The first quad point.", ":param p2:
The second quad point.", ":param p3: The third quad point.", and ":param p4: The
fourth quad point." to match draw_quad and accurately document p3 and p4.

.. versionadded:: 2.5.4
"""

def fill_rect(self, rect: RectLike) -> None:
"""Draw a filled rectangle

:param rect: The :class:`pygame.Rect`-like rectangle to draw.

.. versionadded:: 2.5.4
"""

def fill_triangle(self, p1: Point, p2: Point, p3: Point) -> None:
"""Draw a filled triangle

:param p1: The first triangle point.
:param p2: The second triangle point.
:param p2: The third triangle point.

Comment on lines +177 to +180
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parameter name in fill_triangle docs (p3 mislabelled).

Third point is documented as p2.

Apply this diff:

-        :param p2: The third triangle point.
+        :param p3: The third triangle point.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:param p1: The first triangle point.
:param p2: The second triangle point.
:param p2: The third triangle point.
:param p1: The first triangle point.
:param p2: The second triangle point.
:param p3: The third triangle point.
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/_render.pyi around lines 178 to 181, the docstring
for fill_triangle incorrectly repeats p2 for the third parameter; update the
third param line to ":param p3: The third triangle point." so the parameter name
matches the function signature and documentation.

.. versionadded:: 2.5.4
"""

def get_viewport(self) -> Rect:
"""Get the drawing area on the rendering target

.. versionadded:: 2.5.4
"""

def present(self) -> None:
"""Update the screen with any rendering performed since the previous call

Presents the composed backbuffer to the screen.
Updates the screen with any rendering performed since the previous call.

.. versionadded:: 2.5.4
"""

def set_viewport(self, area: Optional[RectLike]) -> None:
"""Set the drawing area on the rendering target

:param area: A :class:`pygame.Rect` or tuple representing the
drawing area on the target, or ``None`` to use the
entire area of the current rendering target.

.. versionadded:: 2.5.4
"""

def coordinates_to_window(self, point: Point) -> tuple[float, float]: ...
def coordinates_from_window(self, point: Point) -> tuple[float, float]: ...
def present(self) -> None: ...
def set_viewport(self, area: Optional[RectLike]) -> None: ...
def to_surface(
self, surface: Optional[Surface] = None, area: Optional[RectLike] = None
) -> Surface: ...
) -> Surface:
"""Read pixels from current rendering target and create a Surface (slow operation, use sparingly)

Read pixel data from the current rendering target and return a
:class:`pygame.Surface` containing it.

:param Surface surface: A :class:`pygame.Surface` object to read the pixel
data into. It must be large enough to fit the area, otherwise
``ValueError`` is raised.
If set to ``None``, a new surface will be created.
:param area: The area of the screen to read pixels from. The area is
clipped to fit inside the viewport.
If ``None``, the entire viewport is used.

.. note::
This is a very slow operation, due to the overhead of the VRAM to RAM
data transfer and the cost of creating a potentially large
:class:`pygame.Surface`. It should not be used frequently.

.. versionadded:: 2.5.4
"""

@property
def draw_blend_mode(self) -> int: ...
def draw_blend_mode(self) -> int:
"""Get or set the blend mode used for primitive drawing operations

.. versionadded:: 2.5.4
"""
@draw_blend_mode.setter
def draw_blend_mode(self, value: int) -> None: ...
@property
def draw_color(self) -> Color: ...
def draw_color(self) -> Color:
"""Get or set the color used for primitive drawing operations

.. versionadded:: 2.5.4
"""
@draw_color.setter
def draw_color(self, value: ColorLike) -> None: ...
@property
def logical_size(self) -> tuple[int, int]: ...
def logical_size(self) -> tuple[int, int]:
"""Get or set the logical Renderer size (a device independent resolution for rendering)"""
@logical_size.setter
def logical_size(self, value: IntPoint) -> None: ...
@property
def scale(self) -> tuple[float, float]: ...
def scale(self) -> tuple[float, float]:
"""Get the drawing scale for the current rendering target

.. versionadded:: 2.5.4
"""
@scale.setter
def scale(self, value: Point) -> None: ...
@property
def target(self) -> "Texture": ...
def target(self) -> "Texture":
"""Get or set the current rendering target

Gets or sets the current rendering target.
A value of ``None`` means that no custom rendering target was set and the
Renderer's window will be used as the target.

.. versionadded:: 2.5.4
"""
@target.setter
def target(self, value: "Texture") -> None: ...
Comment on lines +265 to 275
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Type mismatch vs. docs: Renderer.target should be Optional[Texture].

Docs say “A value of None means … the Renderer's window will be used”, but the types are non-optional. This impacts type-checkers and user code.

Apply this diff to align type hints and setter:

-    def target(self) -> "Texture":
+    def target(self) -> Optional["Texture"]:
@@
-    def target(self, value: "Texture") -> None: ...
+    def target(self, value: Optional["Texture"]) -> None: ...
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def target(self) -> "Texture":
"""Get or set the current rendering target
Gets or sets the current rendering target.
A value of ``None`` means that no custom rendering target was set and the
Renderer's window will be used as the target.
.. versionadded:: 2.5.4
"""
@target.setter
def target(self, value: "Texture") -> None: ...
def target(self) -> Optional["Texture"]:
"""Get or set the current rendering target
Gets or sets the current rendering target.
A value of ``None`` means that no custom rendering target was set and the
Renderer's window will be used as the target.
.. versionadded:: 2.5.4
"""
@target.setter
def target(self, value: Optional["Texture"]) -> None: ...
🤖 Prompt for AI Agents
In buildconfig/stubs/pygame/_render.pyi around lines 267 to 277, the annotated
types for Renderer.target are non-optional but the docstring states None is a
valid value; update the type hints to Optional["Texture"] for both the getter
return and the setter parameter and ensure typing.Optional is imported (or add
from typing import Optional at top of the stub) so static type-checkers accept
None as a valid value.

@classmethod
def compose_custom_blend_mode(
cls, color_mode: SequenceLike[int], alpha_mode: SequenceLike[int]
) -> int: ...
) -> int:
"""Compose a custom blend mode

Compose a custom blend mode.
See https://wiki.libsdl.org/SDL2/SDL_ComposeCustomBlendMode for more information.

:param color_mode: A tuple ``(srcColorFactor, dstColorFactor, colorOperation)``
:param alpha_mode: A tuple ``(srcAlphaFactor, dstAlphaFactor, alphaOperation)``

:return: A blend mode to be used with :meth:`Renderer.set_draw_blend_mode` and :meth:`Texture.set_blend_mode`.

.. versionadded:: 2.5.4
"""

@classmethod
def from_window(cls, window: Window) -> Renderer: ...
def from_window(cls, window: Window) -> Renderer:
"""Create a Renderer from an existing window

.. versionadded:: 2.5.4
"""

@final
class Texture:
"""Pygame object that represents a texture

.. versionadded:: 2.5.4
"""
def __init__(
self,
renderer: Renderer,
Expand Down Expand Up @@ -147,4 +374,7 @@ class Texture:

@final
class Image:
pass
"""Pygame object that represents a portion of a texture

.. versionadded:: 2.5.4
"""
3 changes: 3 additions & 0 deletions docs/reST/ext/documenters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import autoapi
import autoapi.documenters
from autoapi._objects import PythonClass
from autoapi._mapper import PythonModule
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid hard failing on AutoAPI internals import across versions.

from autoapi._mapper import PythonModule is a private import and may not exist across AutoAPI versions. Wrap it to degrade gracefully.

Apply this diff:

-from autoapi._mapper import PythonModule
+try:
+    from autoapi._mapper import PythonModule as _PythonModule
+except Exception:
+    _PythonModule = None  # AutoAPI version without _mapper.PythonModule
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from autoapi._mapper import PythonModule
try:
from autoapi._mapper import PythonModule as _PythonModule
except Exception:
_PythonModule = None # AutoAPI version without _mapper.PythonModule
🤖 Prompt for AI Agents
In docs/reST/ext/documenters.py around line 4, the direct private import from
autoapi._mapper may not exist across AutoAPI versions; change it to attempt
importing PythonModule in a try/except ImportError block and fall back
gracefully (either import the public equivalent if available or set PythonModule
to None/a sentinel), and ensure any later use of PythonModule checks for the
fallback before using it so the module degrades without hard failing.

import re


Expand Down Expand Up @@ -154,3 +155,5 @@ def setup(app):
{"objtype": f"pg{name}"},
)
)

PythonModule._should_skip = lambda *args, **kwargs: False
2 changes: 1 addition & 1 deletion docs/reST/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ them, this is how you can do it:
Don't forget to report us any problem with the experimental features on `github`_ so we can easily
turn them to stable API in the future ^^.

**Below is currently the list of experimental modules :**
**Below is currently the list of experimental modules:**

:doc:`ref/geometry`
Pygame module for the Circle, Line, and Polygon objects.
Expand Down
Loading