mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
Texture.set_ram_image(_as) now directly accepts buffers with right component size
This commit is contained in:
parent
a757cb47e8
commit
ef986ccfc0
@ -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"
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "internalName_ext.cxx"
|
||||
#include "geomVertexArrayData_ext.cxx"
|
||||
#include "texture_ext.cxx"
|
||||
#include "textureCollection_ext.cxx"
|
||||
|
@ -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;
|
||||
|
147
panda/src/gobj/texture_ext.cxx
Normal file
147
panda/src/gobj/texture_ext.cxx
Normal file
@ -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
panda/src/gobj/texture_ext.h
Normal file
37
panda/src/gobj/texture_ext.h
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user