Source code for libretro.api.video.context

"""Hardware rendering API context types and callbacks."""

from ctypes import Structure, c_bool, c_int, c_uint, c_void_p, cast
from dataclasses import dataclass
from enum import IntEnum

from libretro.api._utils import c_uintptr
from libretro.ctypes import CStringArg, TypedFunctionPointer, c_void_ptr

RETRO_HW_FRAME_BUFFER_VALID = cast((-1), c_void_p)

retro_hw_context_type = c_int
RETRO_HW_CONTEXT_NONE = 0
RETRO_HW_CONTEXT_OPENGL = 1
RETRO_HW_CONTEXT_OPENGLES2 = 2
RETRO_HW_CONTEXT_OPENGL_CORE = 3
RETRO_HW_CONTEXT_OPENGLES3 = 4
RETRO_HW_CONTEXT_OPENGLES_VERSION = 5
RETRO_HW_CONTEXT_VULKAN = 6
RETRO_HW_CONTEXT_D3D11 = 7
RETRO_HW_CONTEXT_D3D10 = 8
RETRO_HW_CONTEXT_D3D12 = 9
RETRO_HW_CONTEXT_D3D9 = 10
RETRO_HW_CONTEXT_DUMMY = 0x7FFFFFFF

HW_FRAME_BUFFER_VALID = RETRO_HW_FRAME_BUFFER_VALID
"""
Passed to :class:`.retro_video_refresh_t` to signal that the next video frame
should be rendered with the GPU context state instead of a software-accessible framebuffer.
"""


[docs] class HardwareContext(IntEnum): """ Hardware rendering API supported by libretro. Corresponds to :c:type:`retro_hw_context_type` in ``libretro.h``. .. seealso:: :class:`.VideoDriver` The :class:`~typing.Protocol` that implements one or more of these context types. """ NONE = RETRO_HW_CONTEXT_NONE """ Software rendering only. .. note:: The active :class:`.VideoDriver` may still use a hardware rendering API, but it won't be exposed to the core. """ OPENGL = RETRO_HW_CONTEXT_OPENGL """OpenGL 2.x, or a newer OpenGL version with the compatibility profile.""" OPENGLES2 = RETRO_HW_CONTEXT_OPENGLES2 """OpenGL ES 2.0.""" OPENGL_CORE = RETRO_HW_CONTEXT_OPENGL_CORE """OpenGL 3.2+ core profile.""" OPENGLES3 = RETRO_HW_CONTEXT_OPENGLES3 """OpenGL ES 3.0.""" OPENGLES_VERSION = RETRO_HW_CONTEXT_OPENGLES_VERSION """OpenGL ES with version specified by :attr:`.version_major` and :attr:`.version_minor`.""" VULKAN = RETRO_HW_CONTEXT_VULKAN """ Vulkan. .. note:: libretro.py doesn't currently support Vulkan contexts. Pull requests are welcome! """ DIRECT3D = 7 """ :deprecated: Use :attr:`.D3D11`, :attr:`.D3D10`, :attr:`.D3D12`, or :attr:`.D3D9` instead. """ D3D11 = RETRO_HW_CONTEXT_D3D11 """ Direct3D 11. .. note:: libretro.py doesn't currently support Direct3D contexts. Pull requests are welcome! """ D3D10 = RETRO_HW_CONTEXT_D3D10 """ Direct3D 10. .. note:: libretro.py doesn't currently support Direct3D contexts. Pull requests are welcome! """ D3D12 = RETRO_HW_CONTEXT_D3D12 """ Direct3D 12. .. note:: libretro.py doesn't currently support Direct3D contexts. Pull requests are welcome! """ D3D9 = RETRO_HW_CONTEXT_D3D9 """ Direct3D 9. .. note:: libretro.py doesn't currently support Direct3D contexts. Pull requests are welcome! """
retro_hw_context_reset_t = TypedFunctionPointer[None, []] """ Notify the core that the hardware rendering context has been (re)created or destroyed. Registered by the :term:`core` and called by the :term:`frontend` when a hardware rendering context is initialized, lost, or about to be torn down. A core should treat all GPU resources as invalid after this is called as a reset and recreate them; for a destroy notification, it should simply free its resources without further GPU calls. Corresponds to :c:type:`retro_hw_context_reset_t` in ``libretro.h``. """ retro_hw_get_current_framebuffer_t = TypedFunctionPointer[c_uintptr, []] """ Return the current frontend-managed hardware framebuffer object. Registered by the :term:`frontend` and called by the :term:`core` to obtain the framebuffer it should render into for the current frame. :return: An opaque :class:`~.libretro.ctypes.c_uintptr` identifying the framebuffer (typically an OpenGL FBO ID). The value may change from frame to frame. .. note:: This callback exists for historical reasons and is only meaningful for OpenGL contexts. Corresponds to :c:type:`retro_hw_get_current_framebuffer_t` in ``libretro.h``. """ retro_hw_get_proc_address_t = TypedFunctionPointer[c_void_ptr, [CStringArg]] """ Look up a function pointer in the active hardware rendering API. Registered by the :term:`frontend` and called by the :term:`core` to obtain entry points such as ``glClear`` or other GPU API functions. :param sym: Name of the symbol to look up, as a :obj:`bytes`-like object. :return: A :class:`~libretro.ctypes.c_void_ptr` to the requested function, or :obj:`None` if the symbol could not be resolved. .. note:: The returned pointer must be cast to the correct function signature before use. Corresponds to :c:type:`retro_hw_get_proc_address_t` in ``libretro.h``. """ # Workaround for ctypes not allowing callbacks to return function pointers
[docs] @dataclass(init=False, slots=True) class retro_hw_render_callback(Structure): """ Description of the hardware rendering context a core requires, with callbacks for reacting to or querying the context. Corresponds to :c:type:`retro_hw_render_callback` in ``libretro.h``. >>> from libretro.api.video import retro_hw_render_callback, HardwareContext >>> cb = retro_hw_render_callback() >>> cb.context_type == HardwareContext.NONE True """ context_type: HardwareContext """Hardware rendering API to use.""" context_reset: retro_hw_context_reset_t | None """ Called when the rendering context is created or reset. .. seealso:: :meth:`.VideoDriver.reinit` The suggested method to call this callback. """ get_current_framebuffer: retro_hw_get_current_framebuffer_t | None """ Return the current hardware framebuffer. Set by the :term:`frontend`. .. note:: This callback exists for historical reasons and is only meaningful for OpenGL contexts. .. seealso:: :attr:`.VideoDriver.current_framebuffer` The suggested property to implement this callback. """ get_proc_address: retro_hw_get_proc_address_t | None """ Looks up a rendering API function by name. Set by the frontend. .. seealso:: :meth:`.VideoDriver.get_proc_address` The suggested method to implement this callback. """ depth: bool """ Whether the framebuffer should have a depth component. .. note:: This field exists for historical reasons and is only meaningful for OpenGL contexts. """ stencil: bool """ Whether the framebuffer should have a stencil component. .. note:: This field exists for historical reasons and is only meaningful for OpenGL contexts. """ bottom_left_origin: bool """Whether to use bottom-left origin convention.""" version_major: int """Major version number for the rendering context.""" version_minor: int """Minor version number for the rendering context.""" cache_context: bool """ Whether the frontend should avoid resetting the context. """ context_destroy: retro_hw_context_reset_t | None """ Called before the context is destroyed. """ debug_context: bool """Whether to create a debug rendering context.""" _fields_ = ( ("context_type", retro_hw_context_type), ("context_reset", retro_hw_context_reset_t), ("get_current_framebuffer", retro_hw_get_current_framebuffer_t), ("get_proc_address", retro_hw_get_proc_address_t), ("depth", c_bool), ("stencil", c_bool), ("bottom_left_origin", c_bool), ("version_major", c_uint), ("version_minor", c_uint), ("cache_context", c_bool), ("context_destroy", retro_hw_context_reset_t), ("debug_context", c_bool), )
[docs] def __init__( self, context_type: HardwareContext = HardwareContext.NONE, context_reset: retro_hw_context_reset_t | None = None, get_current_framebuffer: retro_hw_get_current_framebuffer_t | None = None, get_proc_address: retro_hw_get_proc_address_t | None = None, depth: bool = False, stencil: bool = False, bottom_left_origin: bool = False, version_major: int = 0, version_minor: int = 0, cache_context: bool = False, context_destroy: retro_hw_context_reset_t | None = None, debug_context: bool = False, ): """Create a new :class:`retro_hw_render_callback`.""" self.context_type = context_type self.context_reset = context_reset or retro_hw_context_reset_t() self.get_current_framebuffer = ( get_current_framebuffer or retro_hw_get_current_framebuffer_t() ) self.get_proc_address = get_proc_address or retro_hw_get_proc_address_t() self.depth = depth self.stencil = stencil self.bottom_left_origin = bottom_left_origin self.version_major = version_major self.version_minor = version_minor self.cache_context = cache_context self.context_destroy = context_destroy or retro_hw_context_reset_t() self.debug_context = debug_context
[docs] def __deepcopy__(self, _): """ Return a deep copy of this object. Intended for use with :func:`copy.deepcopy`. """ return retro_hw_render_callback( self.context_type, self.context_reset, self.get_current_framebuffer, self.get_proc_address, self.depth, self.stencil, self.bottom_left_origin, self.version_major, self.version_minor, self.cache_context, self.context_destroy, self.debug_context, )
__all__ = [ "HardwareContext", "retro_hw_context_reset_t", "retro_hw_get_current_framebuffer_t", "retro_hw_get_proc_address_t", "retro_hw_render_callback", "HW_FRAME_BUFFER_VALID", "retro_hw_context_type", ]