Skip to content
Open
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
91 changes: 59 additions & 32 deletions cuda_bindings/tests/test_graphics_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@
from cuda.bindings import runtime as cudart


@contextlib.contextmanager
def _gl_context():
"""
Yield a (tex_id, tex_target) with a current GL context.
def _create_gl_texture():
"""Create a hidden/headless GL context plus a tiny texture to register.

Returns ``(win, tex_id, target)``. Raises on any pyglet/GL failure.
Tries:
1) Windows: hidden WGL window (no EGL)
2) Linux with DISPLAY/wayland: hidden window
3) Linux headless: EGL headless if available
Skips if none work.
"""
pyglet = pytest.importorskip("pyglet")

Expand All @@ -32,41 +31,55 @@ def _gl_context():

# Create a minimal offscreen/hidden context
win = None
if not pyglet.options.get("headless"):
# Hidden window path (WGL on Windows, GLX/WLS on Linux)
from pyglet import gl

config = gl.Config(double_buffer=False)
win = pyglet.window.Window(visible=False, config=config)
win.switch_to()
else:
# Headless EGL path; pyglet will arrange a pbuffer-like headless context
from pyglet.gl import headless # noqa: F401

# Make a tiny texture so we have a real GL object to register
from pyglet.gl import gl as _gl

tex_id = _gl.GLuint(0)
target = _gl.GL_TEXTURE_2D
_gl.glGenTextures(1, ctypes.byref(tex_id))
_gl.glBindTexture(target, tex_id.value)
_gl.glTexParameteri(target, _gl.GL_TEXTURE_MIN_FILTER, _gl.GL_NEAREST)
_gl.glTexParameteri(target, _gl.GL_TEXTURE_MAG_FILTER, _gl.GL_NEAREST)
width, height = 16, 16
_gl.glTexImage2D(target, 0, _gl.GL_RGBA8, width, height, 0, _gl.GL_RGBA, _gl.GL_UNSIGNED_BYTE, None)

return win, tex_id, target


@contextlib.contextmanager
def _gl_context():
"""Yield a (tex_id, tex_target) with a current GL context, or skip."""
win = None
tex_id = None
try:
if not pyglet.options.get("headless"):
# Hidden window path (WGL on Windows, GLX/WLS on Linux)
from pyglet import gl

config = gl.Config(double_buffer=False)
win = pyglet.window.Window(visible=False, config=config)
win.switch_to()
else:
# Headless EGL path; pyglet will arrange a pbuffer-like headless context
from pyglet.gl import headless # noqa: F401

# Make a tiny texture so we have a real GL object to register
from pyglet.gl import gl as _gl

tex_id = _gl.GLuint(0)
_gl.glGenTextures(1, ctypes.byref(tex_id))
target = _gl.GL_TEXTURE_2D
_gl.glBindTexture(target, tex_id.value)
_gl.glTexParameteri(target, _gl.GL_TEXTURE_MIN_FILTER, _gl.GL_NEAREST)
_gl.glTexParameteri(target, _gl.GL_TEXTURE_MAG_FILTER, _gl.GL_NEAREST)
width, height = 16, 16
_gl.glTexImage2D(target, 0, _gl.GL_RGBA8, width, height, 0, _gl.GL_RGBA, _gl.GL_UNSIGNED_BYTE, None)
try:
win, tex_id, target = _create_gl_texture()
except Exception as e:
# Convert any pyglet/GL creation failure into a clean skip.
# The yield below is deliberately NOT inside this handler:
# @contextmanager re-raises the with-body's exception at the yield,
# so catching there would turn a failing assertion in the test into
# a skip, and the test could never fail.
pytest.skip(f"Could not create GL context/texture: {type(e).__name__}: {e}")

yield int(tex_id.value), int(target)

except Exception as e:
# Convert any pyglet/GL creation failure into a clean skip
pytest.skip(f"Could not create GL context/texture: {type(e).__name__}: {e}")
finally:
# Best-effort cleanup
try:
from pyglet.gl import gl as _gl

if tex_id.value:
if tex_id is not None and tex_id.value:
_gl.glDeleteTextures(1, ctypes.byref(tex_id))
except Exception: # noqa: S110
pass
Expand All @@ -77,6 +90,20 @@ def _gl_context():
pass


@pytest.mark.agent_authored(model="claude-opus-5")
def test_gl_context_lets_body_failures_fail(monkeypatch):
"""A failing assertion inside the with-body must not be reported as a skip."""

class FakeTexId:
value = 7

monkeypatch.setattr(sys.modules[__name__], "_create_gl_texture", lambda: (None, FakeTexId(), 0x0DE1))

with pytest.raises(AssertionError, match="body failure"), _gl_context() as (tex_id, tex_target):
assert (tex_id, tex_target) == (7, 0x0DE1)
raise AssertionError("body failure")


@pytest.mark.parametrize(
"flags",
[
Expand Down
Loading