From 2ac4ca33381de82f51b2fb8c605008268c5ca977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Jul 2019 19:27:20 +0200 Subject: [PATCH] python: expose basic Framebuffer. --- src/python/magnum/PyGL.h | 7 +++++ src/python/magnum/gl.cpp | 39 ++++++++++++++++++++++++++++ src/python/magnum/test/test_gl_gl.py | 17 ++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/python/magnum/PyGL.h b/src/python/magnum/PyGL.h index 144c517..49d8e25 100644 --- a/src/python/magnum/PyGL.h +++ b/src/python/magnum/PyGL.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "magnum/bootstrap.h" @@ -41,6 +42,12 @@ struct PyMesh: GL::Mesh { std::vector buffers; }; +struct PyFramebuffer: GL::Framebuffer { + explicit PyFramebuffer(const Range2Di& viewport): GL::Framebuffer{viewport} {} + + std::vector attached; +}; + } #endif diff --git a/src/python/magnum/gl.cpp b/src/python/magnum/gl.cpp index 7f4be3f..cba85fa 100644 --- a/src/python/magnum/gl.cpp +++ b/src/python/magnum/gl.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,13 @@ namespace magnum { void gl(py::module& m) { + /* + Missing APIs: + + GL object labels + limit queries + */ + m.doc() = "OpenGL wrapping layer"; /* Abstract shader program */ @@ -292,6 +300,37 @@ void gl(py::module& m) { NonDestructibleBase defaultFramebuffer{m, "DefaultFramebuffer", "Default framebuffer"}; + NonDestructibleBase framebuffer{m, + "Framebuffer", "Framebuffer"}; + + py::class_{framebuffer, "ColorAttachment", "Color attachment"} + .def(py::init(), "Constructor"); + + py::class_{framebuffer, "BufferAttachment", "Buffer attachment"} + .def(py::init(), "Color buffer") + .def_readonly_static("DEPTH", &GL::Framebuffer::BufferAttachment::Depth, "Depth buffer") + .def_readonly_static("STENCIL", &GL::Framebuffer::BufferAttachment::Stencil, "Stencil buffer") + #if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_TARGET_WEBGL) + .def_readonly_static("DEPTH_STENCIL", &GL::Framebuffer::BufferAttachment::DepthStencil, "Both depth and stencil buffer") + #endif + ; + + py::implicitly_convertible(); + + framebuffer + .def(py::init(), "Constructor") + .def_property_readonly("id", &GL::Framebuffer::id, "OpenGL framebuffer ID") + .def("attach_renderbuffer", [](PyFramebuffer& self, GL::Framebuffer::BufferAttachment attachment, GL::Renderbuffer& renderbuffer) { + self.attachRenderbuffer(attachment, renderbuffer); + + /* Keep a reference to the renderbuffer to avoid it being deleted + before the framebuffer */ + /** @todo isn't there an API for this? */ + self.attached.emplace_back(py::detail::get_object_handle(&renderbuffer, py::detail::get_type_info(typeid(GL::Renderbuffer))), true); + }, "Attach renderbuffer to given buffer") + + .def_readonly("attached", &PyFramebuffer::attached, "Renderbuffer and texture objects referenced by the framebuffer"); + /* An equivalent to this would be m.attr("default_framebuffer") = &GL::defaultFramebuffer; (have to use a & to make it choose return_value_policy::reference diff --git a/src/python/magnum/test/test_gl_gl.py b/src/python/magnum/test/test_gl_gl.py index c764738..b58c810 100644 --- a/src/python/magnum/test/test_gl_gl.py +++ b/src/python/magnum/test/test_gl_gl.py @@ -57,6 +57,23 @@ class DefaultFramebuffer(GLTestCase): # Using it should not crash, leak or cause double-free issues self.assertTrue(gl.default_framebuffer is not None) +class Framebuffer(GLTestCase): + def test(self): + framebuffer = gl.Framebuffer(((0, 0), (4, 4))) + self.assertNotEqual(framebuffer.id, 0) + self.assertEqual(len(framebuffer.attached), 0) + + def test_attach(self): + renderbuffer = gl.Renderbuffer() + renderbuffer.set_storage(gl.RenderbufferFormat.RGBA8, (4, 4)) + renderbuffer_refcount = sys.getrefcount(renderbuffer) + + framebuffer = gl.Framebuffer(((0, 0), (4, 4))) + framebuffer.attach_renderbuffer(gl.Framebuffer.ColorAttachment(0), renderbuffer) + self.assertEqual(len(framebuffer.attached), 1) + self.assertIs(framebuffer.attached[0], renderbuffer) + self.assertEqual(sys.getrefcount(renderbuffer), renderbuffer_refcount + 1) + class Mesh(GLTestCase): def test_init(self): a = gl.Mesh()