From aedff2d70fae468f00e077636e3a2e8fb0f70897 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 24 Mar 2024 15:49:11 +0100 Subject: [PATCH 1/3] Fix DefaultFramebuffer.read() --- arcade/gl/framebuffer.py | 8 ++++++-- tests/unit/gl/test_opengl_framebuffer.py | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arcade/gl/framebuffer.py b/arcade/gl/framebuffer.py index 6db91d835..7131b12d5 100644 --- a/arcade/gl/framebuffer.py +++ b/arcade/gl/framebuffer.py @@ -429,14 +429,18 @@ def read( with self.activate(): # Configure attachment to read from - gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0 + attachment) + if not self.is_default: + gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0 + attachment) + gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1) + gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) if viewport: x, y, width, height = viewport else: x, y, width, height = 0, 0, self._width, self._height data = (gl.GLubyte * (components * component_size * width * height))(0) gl.glReadPixels(x, y, width, height, base_format, pixel_type, data) - gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0) # Reset to default + if not self.is_default: + gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0) # Reset to default return string_at(data, len(data)) diff --git a/tests/unit/gl/test_opengl_framebuffer.py b/tests/unit/gl/test_opengl_framebuffer.py index d8a86c66b..2ebb1d716 100644 --- a/tests/unit/gl/test_opengl_framebuffer.py +++ b/tests/unit/gl/test_opengl_framebuffer.py @@ -156,3 +156,9 @@ def test_resize(ctx): fbo.resize() assert fbo.size == tex.size assert fbo.viewport == (0, 0, *fbo.size) + +def test_read_screen_framebuffer(window): + data = window.ctx.screen.read() + assert isinstance(data, bytes) + byte_size = int(window.width * window.height * 3 * window.get_pixel_ratio()) + assert len(data) == byte_size From 552f662b73f24a9da754fcfa111bd396450de61e Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 24 Mar 2024 15:59:32 +0100 Subject: [PATCH 2/3] Query actual framebuffer size --- tests/unit/gl/test_opengl_framebuffer.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/unit/gl/test_opengl_framebuffer.py b/tests/unit/gl/test_opengl_framebuffer.py index 2ebb1d716..a809945d5 100644 --- a/tests/unit/gl/test_opengl_framebuffer.py +++ b/tests/unit/gl/test_opengl_framebuffer.py @@ -158,7 +158,8 @@ def test_resize(ctx): assert fbo.viewport == (0, 0, *fbo.size) def test_read_screen_framebuffer(window): - data = window.ctx.screen.read() + components = 3 + data = window.ctx.screen.read(components=components) assert isinstance(data, bytes) - byte_size = int(window.width * window.height * 3 * window.get_pixel_ratio()) - assert len(data) == byte_size + w, h = window.get_framebuffer_size() + assert len(data) == w * h * components From ae2287ce5c2d26c182f7cba130b586c1aa9134da Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 24 Mar 2024 21:57:04 +0100 Subject: [PATCH 3/3] Ensure DefaultFramebuffer reports correct size --- arcade/gl/framebuffer.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/arcade/gl/framebuffer.py b/arcade/gl/framebuffer.py index 7131b12d5..dffdb30c2 100644 --- a/arcade/gl/framebuffer.py +++ b/arcade/gl/framebuffer.py @@ -428,17 +428,21 @@ def read( raise ValueError(f"Invalid dtype '{dtype}'") with self.activate(): - # Configure attachment to read from + # Configure attachment to read from. Does not work on default framebuffer. if not self.is_default: gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0 + attachment) + gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) + if viewport: x, y, width, height = viewport else: - x, y, width, height = 0, 0, self._width, self._height + x, y, width, height = 0, 0, *self.size + data = (gl.GLubyte * (components * component_size * width * height))(0) gl.glReadPixels(x, y, width, height, base_format, pixel_type, data) + if not self.is_default: gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0) # Reset to default @@ -575,6 +579,37 @@ def __init__(self, ctx: "Context"): # HACK: Signal the default framebuffer having depth buffer self._depth_attachment = True # type: ignore + @property + def size(self) -> Tuple[int, int]: + """ + Size as a ``(w, h)`` tuple + + :type: tuple (int, int) + """ + return self._ctx.window.get_framebuffer_size() + + @property + def width(self) -> int: + """ + The width of the framebuffer in pixels + + :type: int + """ + return self.size[0] + + @property + def height(self) -> int: + """ + The height of the framebuffer in pixels + + :type: int + """ + return self.size[1] + + def _get_framebuffer_size(self) -> Tuple[int, int]: + """Get the framebuffer size of the window""" + return self._ctx.window.get_framebuffer_size() + def _get_viewport(self) -> Tuple[int, int, int, int]: """ Get or set the framebuffer's viewport.