diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index 2485f28759..004e15fdea 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -14,36 +14,47 @@ #ifndef POINTERTOARRAY_H #define POINTERTOARRAY_H - /* * This file defines the classes PointerToArray and ConstPointerToArray (and * their abbreviations, PTA and CPTA), which are extensions to the PointerTo - * class that support reference-counted arrays. You may think of a - * PointerToArray as the same thing as a traditional C-style array. However, - * it actually stores a pointer to an STL vector, which is then reference- - * counted. Thus, most vector operations may be applied directly to a - * PointerToArray object, including dynamic resizing via push_back() and - * pop_back(). Unlike the PointerTo class, the PointerToArray may store - * pointers to any kind of object, not just those derived from ReferenceCount. + * class that support reference-counted arrays. + * + * You may think of a PointerToArray as the same thing as a traditional + * C-style array. However, it actually stores a pointer to an STL vector, + * which is then reference-counted. Thus, most vector operations may be + * applied directly to a PointerToArray object, including dynamic resizing via + * push_back() and pop_back(). + * + * Unlike the PointerTo class, the PointerToArray may store pointers to any + * kind of object, not just those derived from ReferenceCount. + * * Like PointerTo and ConstPointerTo, the macro abbreviations PTA and CPTA are - * defined for convenience. Some examples of syntax: instead of: + * defined for convenience. + * + * Some examples of syntax: instead of: + * * PTA(int) array(10); int *array = new int[10]; * memset(array, 0, sizeof(int) * 10); memset(array, 0, sizeof(int) * 10); - * array[i] = array[i+1]; array[i] = array[i+1]; num_elements - * = array.size(); (no equivalent) PTA(int) copy = array; - * int *copy = array; Note that in the above example, unlike an STL vector - * (but like a C-style array), assigning a PointerToArray object from another - * simply copies the pointer, and does not copy individual elements. (Of - * course, reference counts are adjusted appropriately7.) If you actually - * wanted an element-by-element copy of the array, you would do this: PTA(int) - * copy(0); Create a pointer to an empty vector. copy.v() = - * array.v(); v() is the STL vector itself. The (0) parameter to - * the constructor in the above example is crucial. When a numeric length - * parameter, such as zero, is given to the constructor, it means to define a - * new STL vector with that number of elements initially in it. If no - * parameter is given, on the other hand, it means the PointerToArray should - * point to nothing--no STL vector is created. This is equivalent to a C - * array that points to NULL. + * array[i] = array[i+1]; array[i] = array[i+1]; + * num_elements = array.size(); (no equivalent) + * + * PTA(int) copy = array; int *copy = array; + * + * Note that in the above example, unlike an STL vector (but like a C-style + * array), assigning a PointerToArray object from another simply copies the + * pointer, and does not copy individual elements. (Of course, reference + * counts are adjusted appropriately.) If you actually wanted an + * element-by-element copy of the array, you would do this: + * + * PTA(int) copy(0); // Create a pointer to an empty vector. + * copy.v() = array.v(); // v() is the STL vector itself. + * + * The (0) parameter to the constructor in the above example is crucial. When + * a numeric length parameter, such as zero, is given to the constructor, it + * means to define a new STL vector with that number of elements initially in + * it. If no parameter is given, on the other hand, it means the + * PointerToArray should point to nothing--no STL vector is created. This is + * equivalent to a C array that points to NULL. */ #include "pandabase.h" diff --git a/panda/src/gobj/p3gobj_ext_composite.cxx b/panda/src/gobj/p3gobj_ext_composite.cxx index 33584e701b..5d71156d01 100644 --- a/panda/src/gobj/p3gobj_ext_composite.cxx +++ b/panda/src/gobj/p3gobj_ext_composite.cxx @@ -1,3 +1,4 @@ #include "internalName_ext.cxx" #include "geomVertexArrayData_ext.cxx" +#include "texture_ext.cxx" #include "textureCollection_ext.cxx" diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 1f125fd7ce..cd05019416 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -445,9 +445,15 @@ PUBLISHED: CPTA_uchar get_ram_image_as(const string &requested_format); INLINE PTA_uchar modify_ram_image(); INLINE PTA_uchar make_ram_image(); +#ifndef CPPPARSER INLINE void set_ram_image(CPTA_uchar image, CompressionMode compression = CM_off, size_t page_size = 0); void set_ram_image_as(CPTA_uchar image, const string &provided_format); +#else + EXTEND void set_ram_image(PyObject *image, CompressionMode compression = CM_off, + size_t page_size = 0); + EXTEND void set_ram_image_as(PyObject *image, const string &provided_format); +#endif INLINE void clear_ram_image(); INLINE void set_keep_ram_image(bool keep_ram_image); virtual bool get_keep_ram_image() const; diff --git a/panda/src/gobj/texture_ext.cxx b/panda/src/gobj/texture_ext.cxx new file mode 100644 index 0000000000..2a462849c0 --- /dev/null +++ b/panda/src/gobj/texture_ext.cxx @@ -0,0 +1,147 @@ +/** + * 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 texture_ext.cxx + * @author rdb + * @date 2016-08-08 + */ + +#include "texture_ext.h" + +#ifndef CPPPARSER +extern Dtool_PyTypedObject Dtool_PointerToArray_unsigned_char; +extern Dtool_PyTypedObject Dtool_ConstPointerToArray_unsigned_char; +#endif + +/** + * Replaces the current system-RAM image with the new data. If compression is + * not CM_off, it indicates that the new data is already pre-compressed in the + * indicated format. + * + * This does *not* affect keep_ram_image. + */ +void Extension:: +set_ram_image(PyObject *image, Texture::CompressionMode compression, + size_t page_size) { + nassertv(compression != Texture::CM_default); + + // Check if perhaps a PointerToArray object was passed in. + if (DtoolCanThisBeAPandaInstance(image)) { + Dtool_PyInstDef *inst = (Dtool_PyInstDef *)image; + + if (inst->_My_Type == &Dtool_ConstPointerToArray_unsigned_char) { + _this->set_ram_image(*(const CPTA_uchar *)inst->_ptr_to_object, compression, page_size); + return; + + } else if (inst->_My_Type == &Dtool_PointerToArray_unsigned_char) { + _this->set_ram_image(*(const PTA_uchar *)inst->_ptr_to_object, compression, page_size); + return; + } + } + +#if PY_VERSION_HEX >= 0x02060000 + if (PyObject_CheckBuffer(image)) { + // User passed a buffer object. + Py_buffer view; + if (PyObject_GetBuffer(image, &view, PyBUF_CONTIG_RO) == -1) { + PyErr_SetString(PyExc_TypeError, + "Texture.set_ram_image() requires a contiguous buffer"); + return; + } + + int component_width = _this->get_component_width(); + if (compression == Texture::CM_off) { + if (view.itemsize != 1 && view.itemsize != component_width) { + PyErr_SetString(PyExc_TypeError, + "buffer.itemsize does not match Texture component size"); + return; + } + + if (view.len % component_width != 0) { + PyErr_Format(PyExc_ValueError, + "byte buffer is not a multiple of %zu bytes", + component_width); + return; + } + } else { + if (view.itemsize != 1) { + PyErr_SetString(PyExc_TypeError, + "buffer.itemsize should be 1 for compressed images"); + return; + } + } + + PTA_uchar data = PTA_uchar::empty_array(view.len, Texture::get_class_type()); + memcpy(data.p(), view.buf, view.len); + _this->set_ram_image(MOVE(data), compression, page_size); + + PyBuffer_Release(&view); + return; + } +#endif + + Dtool_Raise_ArgTypeError(image, 0, "Texture.set_ram_image", "CPTA_uchar or buffer"); +} + +/** + * Replaces the current system-RAM image with the new data, converting it + * first if necessary from the indicated component-order format. See + * get_ram_image_as() for specifications about the format. This method cannot + * support compressed image data or sub-pages; use set_ram_image() for that. + */ +void Extension:: +set_ram_image_as(PyObject *image, const string &provided_format) { + // Check if perhaps a PointerToArray object was passed in. + if (DtoolCanThisBeAPandaInstance(image)) { + Dtool_PyInstDef *inst = (Dtool_PyInstDef *)image; + + if (inst->_My_Type == &Dtool_ConstPointerToArray_unsigned_char) { + _this->set_ram_image_as(*(const CPTA_uchar *)inst->_ptr_to_object, provided_format); + return; + + } else if (inst->_My_Type == &Dtool_PointerToArray_unsigned_char) { + _this->set_ram_image_as(*(const PTA_uchar *)inst->_ptr_to_object, provided_format); + return; + } + } + +#if PY_VERSION_HEX >= 0x02060000 + if (PyObject_CheckBuffer(image)) { + // User passed a buffer object. + Py_buffer view; + if (PyObject_GetBuffer(image, &view, PyBUF_CONTIG_RO) == -1) { + PyErr_SetString(PyExc_TypeError, + "Texture.set_ram_image_as() requires a contiguous buffer"); + return; + } + + int component_width = _this->get_component_width(); + if (view.itemsize != 1 && view.itemsize != component_width) { + PyErr_SetString(PyExc_TypeError, + "buffer.itemsize does not match Texture component size"); + return; + } + + if (view.len % component_width != 0) { + PyErr_Format(PyExc_ValueError, + "byte buffer is not a multiple of %zu bytes", + component_width); + return; + } + + PTA_uchar data = PTA_uchar::empty_array(view.len, Texture::get_class_type()); + memcpy(data.p(), view.buf, view.len); + _this->set_ram_image_as(MOVE(data), provided_format); + + PyBuffer_Release(&view); + return; + } +#endif + + Dtool_Raise_ArgTypeError(image, 0, "Texture.set_ram_image_as", "CPTA_uchar or buffer"); +} diff --git a/panda/src/gobj/texture_ext.h b/panda/src/gobj/texture_ext.h new file mode 100644 index 0000000000..f5b4bb4ccd --- /dev/null +++ b/panda/src/gobj/texture_ext.h @@ -0,0 +1,37 @@ +/** + * 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 texture_ext.h + * @author rdb + * @date 2016-08-08 + */ + +#ifndef TEXTURE_EXT_H +#define TEXTURE_EXT_H + +#ifndef CPPPARSER + +#include "extension.h" +#include "py_panda.h" +#include "texture.h" + +/** + * This class defines the extension methods for Texture, which are + * called instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + void set_ram_image(PyObject *image, Texture::CompressionMode compression = Texture::CM_off, + size_t page_size = 0); + void set_ram_image_as(PyObject *image, const string &provided_format); +}; + +#endif // CPPPARSER + +#endif // TEXTURE_EXT_H