/** * 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 renderState_ext.cxx * @author CFSworks * @date 2014-03-31 */ #include "renderState_ext.h" #ifdef HAVE_PYTHON /** * Returns a RenderState with a given number of attributes set. */ CPT(RenderState) Extension:: make(PyObject *args, PyObject *kwds) { extern struct Dtool_PyTypedObject Dtool_RenderAttrib; Py_ssize_t num_attribs = PyTuple_GET_SIZE(args); // Check for the override keyword argument. PyObject *py_override = nullptr; if (kwds != nullptr && PyDict_GET_SIZE(kwds) > 0) { if (PyDict_GET_SIZE(kwds) > 1) { Dtool_Raise_TypeError("RenderState.make() received an unexpected keyword argument"); return nullptr; } PyObject *key; Py_ssize_t ppos = 0; if (!PyDict_Next(kwds, &ppos, &key, &py_override)) { return nullptr; } // We got the item, we just need to make sure that it had the right key. if (!PyUnicode_CheckExact(key) || !_PyUnicode_EqualToASCIIString(key, "override")) { Dtool_Raise_TypeError("RenderState.make() received an unexpected keyword argument"); return nullptr; } if (!PyLong_Check(py_override)) { Dtool_Raise_TypeError("RenderState.make() override argument should be int"); return nullptr; } } else if (num_attribs > 1 && PyLong_Check(PyTuple_GET_ITEM(args, num_attribs - 1))) { // It was specified as last positional argument. py_override = PyTuple_GET_ITEM(args, --num_attribs); } int override = 0; if (py_override != nullptr) { override = _PyLong_AsInt(py_override); if (override == -1 && _PyErr_OCCURRED()) { return nullptr; } } const RenderAttrib **attribs = (const RenderAttrib **)alloca(sizeof(RenderAttrib *) * num_attribs); for (Py_ssize_t i = 0; i < num_attribs; ++i) { PyObject *arg = PyTuple_GET_ITEM(args, i); if (!DtoolInstance_GetPointer(arg, attribs[i], Dtool_RenderAttrib)) { Dtool_Raise_ArgTypeError(arg, i, "RenderState.make", "RenderAttrib"); return nullptr; } } return RenderState::make(attribs, num_attribs, override); } /** * Returns a list of 2-tuples that represents the composition cache. For each * tuple in the list, the first element is the source render, and the second * is the result render. If both are None, there is no entry in the cache at * that slot. * * In general, a->compose(source) == result. * * This has no practical value other than for examining the cache for * performance analysis. */ PyObject *Extension:: get_composition_cache() const { extern struct Dtool_PyTypedObject Dtool_RenderState; LightReMutexHolder holder(*RenderState::_states_lock); size_t cache_size = _this->_composition_cache.get_num_entries(); PyObject *list = PyList_New(cache_size); for (size_t i = 0; i < cache_size; ++i) { PyObject *tuple = PyTuple_New(2); PyObject *a, *b; const RenderState *source = _this->_composition_cache.get_key(i); if (source == nullptr) { a = Py_None; Py_INCREF(a); } else { source->ref(); a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState, true, true, source->get_type_index()); } const RenderState *result = _this->_composition_cache.get_data(i)._result; if (result == nullptr) { b = Py_None; Py_INCREF(b); } else { result->ref(); b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState, true, true, result->get_type_index()); } PyTuple_SET_ITEM(tuple, 0, a); PyTuple_SET_ITEM(tuple, 1, b); PyList_SET_ITEM(list, i, tuple); } return list; } /** * Returns a list of 2-tuples that represents the invert_composition cache. * For each tuple in the list, the first element is the source render, and the * second is the result render. If both are None, there is no entry in the * cache at that slot. * * In general, a->invert_compose(source) == result. * * This has no practical value other than for examining the cache for * performance analysis. */ PyObject *Extension:: get_invert_composition_cache() const { extern struct Dtool_PyTypedObject Dtool_RenderState; LightReMutexHolder holder(*RenderState::_states_lock); size_t cache_size = _this->_invert_composition_cache.get_num_entries(); PyObject *list = PyList_New(cache_size); for (size_t i = 0; i < cache_size; ++i) { PyObject *tuple = PyTuple_New(2); PyObject *a, *b; const RenderState *source = _this->_invert_composition_cache.get_key(i); if (source == nullptr) { a = Py_None; Py_INCREF(a); } else { source->ref(); a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState, true, true, source->get_type_index()); } const RenderState *result = _this->_invert_composition_cache.get_data(i)._result; if (result == nullptr) { b = Py_None; Py_INCREF(b); } else { result->ref(); b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState, true, true, result->get_type_index()); } PyTuple_SET_ITEM(tuple, 0, a); PyTuple_SET_ITEM(tuple, 1, b); PyList_SET_ITEM(list, i, tuple); } return list; } /** * Returns a list of all of the RenderState objects in the state cache. The * order of elements in this cache is arbitrary. */ PyObject *Extension:: get_states() { extern struct Dtool_PyTypedObject Dtool_RenderState; LightReMutexHolder holder(*RenderState::_states_lock); size_t num_states = RenderState::_states.get_num_entries(); PyObject *list = PyList_New(num_states); size_t i = 0; size_t size = RenderState::_states.get_num_entries(); for (size_t si = 0; si < size; ++si) { const RenderState *state = RenderState::_states.get_key(si); state->ref(); PyObject *a = DTool_CreatePyInstanceTyped((void *)state, Dtool_RenderState, true, true, state->get_type_index()); nassertr(i < num_states, list); PyList_SET_ITEM(list, i, a); ++i; } nassertr(i == num_states, list); return list; } /** * Returns a list of all of the "unused" RenderState objects in the state * cache. See get_num_unused_states(). */ PyObject *Extension:: get_unused_states() { extern struct Dtool_PyTypedObject Dtool_RenderState; LightReMutexHolder holder(*RenderState::_states_lock); PyObject *list = PyList_New(0); size_t size = RenderState::_states.get_num_entries(); for (size_t si = 0; si < size; ++si) { const RenderState *state = RenderState::_states.get_key(si); if (state->get_cache_ref_count() == state->get_ref_count()) { state->ref(); PyObject *a = DTool_CreatePyInstanceTyped((void *)state, Dtool_RenderState, true, true, state->get_type_index()); PyList_Append(list, a); Py_DECREF(a); } } return list; } #endif // HAVE_PYTHON