Skip to content

Commit e26753e

Browse files
authored
Fix DefaultFramebuffer.read() (#2034)
* Fix DefaultFramebuffer.read() * Query actual framebuffer size * Ensure DefaultFramebuffer reports correct size
1 parent a3392cf commit e26753e

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

arcade/gl/framebuffer.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -428,15 +428,23 @@ def read(
428428
raise ValueError(f"Invalid dtype '{dtype}'")
429429

430430
with self.activate():
431-
# Configure attachment to read from
432-
gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0 + attachment)
431+
# Configure attachment to read from. Does not work on default framebuffer.
432+
if not self.is_default:
433+
gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0 + attachment)
434+
435+
gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
436+
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
437+
433438
if viewport:
434439
x, y, width, height = viewport
435440
else:
436-
x, y, width, height = 0, 0, self._width, self._height
441+
x, y, width, height = 0, 0, *self.size
442+
437443
data = (gl.GLubyte * (components * component_size * width * height))(0)
438444
gl.glReadPixels(x, y, width, height, base_format, pixel_type, data)
439-
gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0) # Reset to default
445+
446+
if not self.is_default:
447+
gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0) # Reset to default
440448

441449
return string_at(data, len(data))
442450

@@ -571,6 +579,37 @@ def __init__(self, ctx: "Context"):
571579
# HACK: Signal the default framebuffer having depth buffer
572580
self._depth_attachment = True # type: ignore
573581

582+
@property
583+
def size(self) -> Tuple[int, int]:
584+
"""
585+
Size as a ``(w, h)`` tuple
586+
587+
:type: tuple (int, int)
588+
"""
589+
return self._ctx.window.get_framebuffer_size()
590+
591+
@property
592+
def width(self) -> int:
593+
"""
594+
The width of the framebuffer in pixels
595+
596+
:type: int
597+
"""
598+
return self.size[0]
599+
600+
@property
601+
def height(self) -> int:
602+
"""
603+
The height of the framebuffer in pixels
604+
605+
:type: int
606+
"""
607+
return self.size[1]
608+
609+
def _get_framebuffer_size(self) -> Tuple[int, int]:
610+
"""Get the framebuffer size of the window"""
611+
return self._ctx.window.get_framebuffer_size()
612+
574613
def _get_viewport(self) -> Tuple[int, int, int, int]:
575614
"""
576615
Get or set the framebuffer's viewport.

tests/unit/gl/test_opengl_framebuffer.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,10 @@ def test_resize(ctx):
156156
fbo.resize()
157157
assert fbo.size == tex.size
158158
assert fbo.viewport == (0, 0, *fbo.size)
159+
160+
def test_read_screen_framebuffer(window):
161+
components = 3
162+
data = window.ctx.screen.read(components=components)
163+
assert isinstance(data, bytes)
164+
w, h = window.get_framebuffer_size()
165+
assert len(data) == w * h * components

0 commit comments

Comments
 (0)