diff --git a/panda/src/display/CMakeLists.txt b/panda/src/display/CMakeLists.txt index 2b9e11b426..56e9552d9b 100644 --- a/panda/src/display/CMakeLists.txt +++ b/panda/src/display/CMakeLists.txt @@ -67,6 +67,8 @@ set(P3DISPLAY_SOURCES ) set(P3DISPLAY_IGATEEXT + frameBufferProperties_ext.cxx + frameBufferProperties_ext.h graphicsPipeSelection_ext.cxx graphicsPipeSelection_ext.h graphicsStateGuardian_ext.cxx diff --git a/panda/src/display/frameBufferProperties.h b/panda/src/display/frameBufferProperties.h index 152f2dccc7..69993a0d0d 100644 --- a/panda/src/display/frameBufferProperties.h +++ b/panda/src/display/frameBufferProperties.h @@ -16,6 +16,7 @@ #include "pandabase.h" #include "pnotify.h" +#include "extension.h" class Texture; @@ -143,6 +144,9 @@ PUBLISHED: MAKE_PROPERTY(float_color, get_float_color, set_float_color); MAKE_PROPERTY(float_depth, get_float_depth, set_float_depth); + EXTENSION(PyObject *__getstate__() const); + EXTENSION(void __setstate__(PyObject *self, PyObject *state)); + // Other. constexpr FrameBufferProperties() = default; @@ -169,6 +173,8 @@ PUBLISHED: bool setup_color_texture(Texture *tex) const; bool setup_depth_texture(Texture *tex) const; + + friend class Extension; }; INLINE std::ostream &operator << (std::ostream &out, const FrameBufferProperties &properties); diff --git a/panda/src/display/frameBufferProperties_ext.cxx b/panda/src/display/frameBufferProperties_ext.cxx new file mode 100644 index 0000000000..96ed9d3afe --- /dev/null +++ b/panda/src/display/frameBufferProperties_ext.cxx @@ -0,0 +1,75 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file frameBufferProperties_ext.cxx + * @author rdb + * @date 2021-12-13 + */ + +#include "frameBufferProperties_ext.h" + +#ifdef HAVE_PYTHON + +/** + * Returns the properties as a dictionary. + */ +PyObject *Extension:: +__getstate__() const { + static const char *props[FrameBufferProperties::FBP_COUNT] = {"depth_bits", "color_bits", "red_bits", "green_bits", "blue_bits", "alpha_bits", "stencil_bits", "accum_bits", "aux_rgba", "aux_hrgba", "aux_float", "multisamples", "coverage_samples", "back_buffers"}; + static const char *flags[] = {"indexed_color", "rgb_color", "stereo", "force_hardware", "force_software", "srgb_color", "float_color", "float_depth", nullptr}; + + PyObject *state = PyDict_New(); + + for (size_t i = 0; i < FrameBufferProperties::FBP_COUNT; ++i) { + if (_this->_specified & (1 << i)) { + PyObject *value = PyLong_FromLong(_this->_property[i]); + PyDict_SetItemString(state, props[i], value); + Py_DECREF(value); + } + } + + for (size_t i = 0; flags[i] != nullptr; ++i) { + if (_this->_flags_specified & (1 << i)) { + PyObject *value = (_this->_flags & (1 << i)) ? Py_True : Py_False; + PyDict_SetItemString(state, flags[i], value); + } + } + + return state; +} + +/** + * + */ +void Extension:: +__setstate__(PyObject *self, PyObject *props) { + PyTypeObject *type = Py_TYPE(self); + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(props, &pos, &key, &value)) { + // Look for a writable property on the type by this name. + PyObject *descr = _PyType_Lookup(type, key); + + if (descr != nullptr && Py_TYPE(descr)->tp_descr_set != nullptr) { + if (Py_TYPE(descr)->tp_descr_set(descr, self, value) < 0) { + return; + } + } else { + PyObject *key_repr = PyObject_Repr(key); + PyErr_Format(PyExc_TypeError, + "%.100s is an invalid framebuffer property", + PyUnicode_AsUTF8(key_repr) + ); + Py_DECREF(key_repr); + return; + } + } +} + +#endif // HAVE_PYTHON diff --git a/panda/src/display/frameBufferProperties_ext.h b/panda/src/display/frameBufferProperties_ext.h new file mode 100644 index 0000000000..b1c823d552 --- /dev/null +++ b/panda/src/display/frameBufferProperties_ext.h @@ -0,0 +1,38 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file frameBufferProperties_ext.h + * @author rdb + * @date 2021-12-13 + */ + +#ifndef FRAMEBUFFERPROPERTIES_EXT_H +#define FRAMEBUFFERPROPERTIES_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "frameBufferProperties.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for FrameBufferProperties, which are + * called instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + PyObject *__getstate__() const; + void __setstate__(PyObject *self, PyObject *state); +}; + +#endif // HAVE_PYTHON + +#endif // FRAMEBUFFERPROPERTIES_EXT_H diff --git a/panda/src/display/p3display_ext_composite.cxx b/panda/src/display/p3display_ext_composite.cxx index e4588474d0..71e5074d06 100644 --- a/panda/src/display/p3display_ext_composite.cxx +++ b/panda/src/display/p3display_ext_composite.cxx @@ -1,3 +1,4 @@ +#include "frameBufferProperties_ext.cxx" #include "graphicsPipeSelection_ext.cxx" #include "graphicsStateGuardian_ext.cxx" #include "graphicsWindow_ext.cxx"