Kaynağa Gözat

Texture.set_ram_image(_as) now directly accepts buffers with right component size

rdb 9 yıl önce
ebeveyn
işleme
ef986ccfc0

+ 35 - 24
panda/src/express/pointerToArray.h

@@ -14,36 +14,47 @@
 #ifndef POINTERTOARRAY_H
 #ifndef POINTERTOARRAY_H
 #define POINTERTOARRAY_H
 #define POINTERTOARRAY_H
 
 
-
 /*
 /*
  * This file defines the classes PointerToArray and ConstPointerToArray (and
  * This file defines the classes PointerToArray and ConstPointerToArray (and
  * their abbreviations, PTA and CPTA), which are extensions to the PointerTo
  * 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
  * 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];
  * PTA(int) array(10);                     int *array = new int[10];
  * memset(array, 0, sizeof(int) * 10);     memset(array, 0, sizeof(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"
 #include "pandabase.h"

+ 1 - 0
panda/src/gobj/p3gobj_ext_composite.cxx

@@ -1,3 +1,4 @@
 #include "internalName_ext.cxx"
 #include "internalName_ext.cxx"
 #include "geomVertexArrayData_ext.cxx"
 #include "geomVertexArrayData_ext.cxx"
+#include "texture_ext.cxx"
 #include "textureCollection_ext.cxx"
 #include "textureCollection_ext.cxx"

+ 6 - 0
panda/src/gobj/texture.h

@@ -445,9 +445,15 @@ PUBLISHED:
   CPTA_uchar get_ram_image_as(const string &requested_format);
   CPTA_uchar get_ram_image_as(const string &requested_format);
   INLINE PTA_uchar modify_ram_image();
   INLINE PTA_uchar modify_ram_image();
   INLINE PTA_uchar make_ram_image();
   INLINE PTA_uchar make_ram_image();
+#ifndef CPPPARSER
   INLINE void set_ram_image(CPTA_uchar image, CompressionMode compression = CM_off,
   INLINE void set_ram_image(CPTA_uchar image, CompressionMode compression = CM_off,
                             size_t page_size = 0);
                             size_t page_size = 0);
   void set_ram_image_as(CPTA_uchar image, const string &provided_format);
   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 clear_ram_image();
   INLINE void set_keep_ram_image(bool keep_ram_image);
   INLINE void set_keep_ram_image(bool keep_ram_image);
   virtual bool get_keep_ram_image() const;
   virtual bool get_keep_ram_image() const;

+ 147 - 0
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<Texture>::
+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<Texture>::
+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");
+}

+ 37 - 0
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<Texture> : public ExtensionBase<Texture> {
+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