From 98ffa974aca633aef0fca1e604d7007f592d3469 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Mar 2014 17:32:59 +0000 Subject: [PATCH 01/26] Make string coercible into ButtonHandle --- panda/src/putil/buttonHandle.cxx | 16 ++++++++++++++++ panda/src/putil/buttonHandle.h | 1 + 2 files changed, 17 insertions(+) diff --git a/panda/src/putil/buttonHandle.cxx b/panda/src/putil/buttonHandle.cxx index e37f0f738d..49d17eeea3 100644 --- a/panda/src/putil/buttonHandle.cxx +++ b/panda/src/putil/buttonHandle.cxx @@ -20,6 +20,22 @@ ButtonHandle ButtonHandle::_none; TypeHandle ButtonHandle::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: ButtonHandle::Constructor +// Access: Published +// Description: Constructs a ButtonHandle with the corresponding +// name, which is looked up in the ButtonRegistry. +// This exists for the purpose of being able to +// automatically coerce a string into a ButtonHandle; +// for most purposes, you should use either the static +// KeyboardButton/MouseButton getters or +// ButtonRegistry::register_button(). +//////////////////////////////////////////////////////////////////// +ButtonHandle:: +ButtonHandle(const string &name) { + _index = ButtonRegistry::ptr()->get_button(name)._index; +} + //////////////////////////////////////////////////////////////////// // Function: ButtonHandle::get_name // Access: Public diff --git a/panda/src/putil/buttonHandle.h b/panda/src/putil/buttonHandle.h index cd946bdfc3..909458c32c 100644 --- a/panda/src/putil/buttonHandle.h +++ b/panda/src/putil/buttonHandle.h @@ -29,6 +29,7 @@ class EXPCL_PANDA_PUTIL ButtonHandle { PUBLISHED: INLINE ButtonHandle(); INLINE ButtonHandle(int index); + ButtonHandle(const string &name); public: INLINE ButtonHandle(const ButtonHandle ©); From b1e95feb3bacaf6b970a436e54708923efbb8d76 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Mar 2014 17:35:31 +0000 Subject: [PATCH 02/26] Add ButtonMap class / window.get_button_map() for querying keyboard layout + X11 implementation thereof --- panda/src/display/graphicsWindow.cxx | 23 +++- panda/src/display/graphicsWindow.h | 3 +- panda/src/putil/Sources.pp | 12 +- panda/src/putil/buttonMap.I | 141 +++++++++++++++++++++ panda/src/putil/buttonMap.cxx | 33 +++++ panda/src/putil/buttonMap.h | 78 ++++++++++++ panda/src/putil/buttonRegistry.cxx | 19 +++ panda/src/putil/buttonRegistry.h | 1 + panda/src/putil/config_util.cxx | 2 + panda/src/putil/p3putil_composite1.cxx | 1 + panda/src/x11display/x11GraphicsWindow.cxx | 37 +++++- panda/src/x11display/x11GraphicsWindow.h | 5 +- 12 files changed, 340 insertions(+), 15 deletions(-) create mode 100644 panda/src/putil/buttonMap.I create mode 100644 panda/src/putil/buttonMap.cxx create mode 100644 panda/src/putil/buttonMap.h diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index 99ec1e4eb3..36be7cb270 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -77,8 +77,8 @@ GraphicsWindow:: // Clean up python event handlers. #ifdef HAVE_PYTHON PythonWinProcClasses::iterator iter; - for (iter = _python_window_proc_classes.begin(); - iter != _python_window_proc_classes.end(); + for (iter = _python_window_proc_classes.begin(); + iter != _python_window_proc_classes.end(); ++iter) { delete *iter; } @@ -340,6 +340,17 @@ has_keyboard(int device) const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: x11GraphicsWindow::get_keyboard_map +// Access: Published, Virtual +// Description: Returns a ButtonMap containing the association +// between raw buttons and virtual buttons. +//////////////////////////////////////////////////////////////////// +ButtonMap *GraphicsWindow:: +get_keyboard_map() const { + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::enable_pointer_events // Access: Published @@ -391,8 +402,10 @@ disable_pointer_mode(int device) { //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::get_pointer // Access: Published -// Description: Returns the MouseData associated with the nth input -// device's pointer. +// Description: Returns the MouseData associated with the nth +// input device's pointer. This is deprecated; use +// get_pointer_device().get_pointer() instead, or for +// raw mice, use the InputDeviceManager interface. //////////////////////////////////////////////////////////////////// MouseData GraphicsWindow:: get_pointer(int device) const { @@ -409,7 +422,7 @@ get_pointer(int device) const { // Function: GraphicsWindow::move_pointer // Access: Published, Virtual // Description: Forces the pointer to the indicated position within -// the window, if possible. +// the window, if possible. // // Returns true if successful, false on failure. This // may fail if the mouse is not currently within the diff --git a/panda/src/display/graphicsWindow.h b/panda/src/display/graphicsWindow.h index 00ded5833f..2dfe1c3f60 100644 --- a/panda/src/display/graphicsWindow.h +++ b/panda/src/display/graphicsWindow.h @@ -29,6 +29,7 @@ #include "modifierButtons.h" #include "buttonEvent.h" #include "keyboardButton.h" +#include "buttonMap.h" #include "pnotify.h" #include "lightMutex.h" #include "lightReMutex.h" @@ -82,7 +83,7 @@ PUBLISHED: MAKE_SEQ(get_input_device_names, get_num_input_devices, get_input_device_name); bool has_pointer(int device) const; bool has_keyboard(int device) const; - + virtual ButtonMap *get_keyboard_map() const; void enable_pointer_events(int device); void disable_pointer_events(int device); diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index 6134d73f7c..a3046d68fe 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -21,8 +21,9 @@ bamWriter.I bamWriter.h \ bitArray.I bitArray.h \ bitMask.I bitMask.h \ - buttonHandle.I \ - buttonHandle.h buttonRegistry.I buttonRegistry.h \ + buttonHandle.I buttonHandle.h \ + buttonMap.I buttonMap.h \ + buttonRegistry.I buttonRegistry.h \ cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \ callbackData.h callbackData.I \ callbackObject.h callbackObject.I \ @@ -84,7 +85,7 @@ bamWriter.cxx \ bitArray.cxx \ bitMask.cxx \ - buttonHandle.cxx buttonRegistry.cxx \ + buttonHandle.cxx buttonMap.cxx buttonRegistry.cxx \ cachedTypedWritableReferenceCount.cxx \ callbackData.cxx \ callbackObject.cxx \ @@ -132,8 +133,9 @@ bamWriter.I bamWriter.h \ bitArray.I bitArray.h \ bitMask.I bitMask.h \ - buttonHandle.I buttonHandle.h buttonRegistry.I \ - buttonRegistry.h \ + buttonHandle.I buttonHandle.h \ + buttonMap.I buttonMap.h \ + buttonRegistry.I buttonRegistry.h \ cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \ callbackData.h callbackData.I \ callbackObject.h callbackObject.I \ diff --git a/panda/src/putil/buttonMap.I b/panda/src/putil/buttonMap.I new file mode 100644 index 0000000000..e51b3c5a0d --- /dev/null +++ b/panda/src/putil/buttonMap.I @@ -0,0 +1,141 @@ +// Filename: buttonMap.I +// Created by: rdb (09Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::get_num_buttons +// Access: Published +// Description: Returns the number of buttons that this button +// mapping specifies. +//////////////////////////////////////////////////////////////////// +INLINE int ButtonMap:: +get_num_buttons() const { + return _buttons.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::get_raw_button +// Access: Published +// Description: Returns the underlying raw button associated with +// the nth button. +//////////////////////////////////////////////////////////////////// +INLINE ButtonHandle ButtonMap:: +get_raw_button(int i) const { + return _buttons[i]->_raw; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::get_mapped_button +// Access: Published +// Description: Returns the nth mapped button, meaning the button +// that the nth raw button is mapped to. +//////////////////////////////////////////////////////////////////// +INLINE ButtonHandle ButtonMap:: +get_mapped_button(int i) const { + return _buttons[i]->_mapped; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::get_mapped_button_text +// Access: Published +// Description: Returns the text associated with the nth mapped +// button, meaning the button that the nth raw +// button is mapped to. +//////////////////////////////////////////////////////////////////// +INLINE const string &ButtonMap:: +get_mapped_button_text(int i) const { + return _buttons[i]->_text; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::get_mapped_button +// Access: Published +// Description: Returns the button that the given button is mapped +// to, or ButtonHandle::none() if this map does not +// specify a mapped button for the given raw button. +//////////////////////////////////////////////////////////////////// +INLINE ButtonHandle ButtonMap:: +get_mapped_button(ButtonHandle raw) const { + pmap::const_iterator it; + it = _button_map.find(raw.get_index()); + if (it == _button_map.end()) { + return ButtonHandle::none(); + } else { + return it->second._mapped; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::get_mapped_button +// Access: Published +// Description: Returns the button that the given button is mapped +// to, or ButtonHandle::none() if this map does not +// specify a mapped button for the given raw button. +//////////////////////////////////////////////////////////////////// +INLINE ButtonHandle ButtonMap:: +get_mapped_button(const string &raw_name) const { + ButtonHandle raw_button = ButtonRegistry::ptr()->find_button(raw_name); + if (raw_button == ButtonHandle::none()) { + return ButtonHandle::none(); + } else { + return get_mapped_button(raw_button); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtoMap::get_mapped_button_text +// Access: Published +// Description: If the button map specifies a special name for the +// button (eg. if the operating system or keyboard +// device has a localized name describing the key), +// returns it, or the empty string otherwise. +// +// Note that this is not the same as +// get_mapped_button().get_name(), which returns the +// name of the Panda event associated with the button. +//////////////////////////////////////////////////////////////////// +INLINE const string &ButtonMap:: +get_mapped_button_text(ButtonHandle raw) const { + pmap::const_iterator it; + it = _button_map.find(raw.get_index()); + if (it == _button_map.end()) { + static const string empty = ""; + return empty; + } else { + return it->second._text; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtoMap::get_mapped_button_text +// Access: Published +// Description: If the button map specifies a special name for the +// button (eg. if the operating system or keyboard +// device has a localized name describing the key), +// returns it, or the empty string otherwise. +// +// Note that this is not the same as +// get_mapped_button().get_name(), which returns the +// name of the Panda event associated with the button. +//////////////////////////////////////////////////////////////////// +INLINE const string &ButtonMap:: +get_mapped_button_text(const string &raw_name) const { + ButtonHandle raw_button = ButtonRegistry::ptr()->find_button(raw_name); + if (raw_button == ButtonHandle::none()) { + static const string empty = ""; + return empty; + } else { + return get_mapped_button_text(raw_button); + } +} diff --git a/panda/src/putil/buttonMap.cxx b/panda/src/putil/buttonMap.cxx new file mode 100644 index 0000000000..1452b4542c --- /dev/null +++ b/panda/src/putil/buttonMap.cxx @@ -0,0 +1,33 @@ +// Filename: buttonMap.cxx +// Created by: rdb (09Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#include "buttonMap.h" + +TypeHandle ButtonMap::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::map_button +// Access: Public +// Description: Registers a new button mapping. +//////////////////////////////////////////////////////////////////// +void ButtonMap:: +map_button(ButtonHandle raw_button, ButtonHandle button, const string &text) { + int index = raw_button.get_index(); + ButtonNode bnode; + bnode._raw = raw_button; + bnode._mapped = button; + bnode._text = text; + _button_map[index] = bnode; + _buttons.push_back(&_button_map[index]); +} diff --git a/panda/src/putil/buttonMap.h b/panda/src/putil/buttonMap.h new file mode 100644 index 0000000000..a6ca416071 --- /dev/null +++ b/panda/src/putil/buttonMap.h @@ -0,0 +1,78 @@ +// Filename: buttonMap.h +// Created by: rdb (07Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef BUTTONMAP_H +#define BUTTONMAP_H + +#include "pandabase.h" +#include "typedReferenceCount.h" +#include "buttonHandle.h" +#include "buttonRegistry.h" +#include "pmap.h" + +//////////////////////////////////////////////////////////////////// +// Class : ButtonMap +// Description : This class represents a map containing all of the +// buttons of a (keyboard) device, though it can also +// be used as a generic mapping between ButtonHandles. +// It maps an underlying 'raw' button to a 'virtual' +// button, which may optionally be associated with an +// appropriate platform-specific name for the button. +//////////////////////////////////////////////////////////////////// +class ButtonMap : public TypedReferenceCount { +PUBLISHED: + INLINE int get_num_buttons() const; + INLINE ButtonHandle get_raw_button(int i) const; + INLINE ButtonHandle get_mapped_button(int i) const; + INLINE const string &get_mapped_button_text(int i) const; + + INLINE ButtonHandle get_mapped_button(ButtonHandle raw) const; + INLINE ButtonHandle get_mapped_button(const string &raw_name) const; + INLINE const string &get_mapped_button_text(ButtonHandle raw) const; + INLINE const string &get_mapped_button_text(const string &raw_name) const; + +public: + void map_button(ButtonHandle raw_button, ButtonHandle button, const string &text = ""); + +private: + struct ButtonNode { + ButtonHandle _raw; + ButtonHandle _mapped; + string _text; + }; + + pmap _button_map; + pvector _buttons; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "ButtonMap", + TypedReferenceCount::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "buttonMap.I" + +#endif diff --git a/panda/src/putil/buttonRegistry.cxx b/panda/src/putil/buttonRegistry.cxx index 44e6d410b1..ef94897dbd 100644 --- a/panda/src/putil/buttonRegistry.cxx +++ b/panda/src/putil/buttonRegistry.cxx @@ -131,6 +131,25 @@ get_button(const string &name) { return button; } +//////////////////////////////////////////////////////////////////// +// Function: ButtonRegistry::find_button +// Access: Published +// Description: Finds a ButtonHandle in the registry matching the +// indicated name. If there is no such ButtonHandle, +// returns ButtonHandle::none(). +//////////////////////////////////////////////////////////////////// +ButtonHandle ButtonRegistry:: +find_button(const string &name) { + NameRegistry::const_iterator ri; + ri = _name_registry.find(name); + + if (ri != _name_registry.end()) { + return (*ri).second->_handle; + } + + return ButtonHandle::none(); +} + //////////////////////////////////////////////////////////////////// // Function: ButtonRegistry::find_ascii_button // Access: Published diff --git a/panda/src/putil/buttonRegistry.h b/panda/src/putil/buttonRegistry.h index cb75e7a847..16f842a35f 100644 --- a/panda/src/putil/buttonRegistry.h +++ b/panda/src/putil/buttonRegistry.h @@ -48,6 +48,7 @@ public: PUBLISHED: ButtonHandle get_button(const string &name); + ButtonHandle find_button(const string &name); ButtonHandle find_ascii_button(char ascii_equivalent) const; void write(ostream &out) const; diff --git a/panda/src/putil/config_util.cxx b/panda/src/putil/config_util.cxx index 6795d69ea8..89b71a6b3f 100644 --- a/panda/src/putil/config_util.cxx +++ b/panda/src/putil/config_util.cxx @@ -21,6 +21,7 @@ #include "bitArray.h" #include "bitMask.h" #include "buttonHandle.h" +#include "buttonMap.h" #include "cachedTypedWritableReferenceCount.h" #include "callbackData.h" #include "callbackObject.h" @@ -186,6 +187,7 @@ init_libputil() { BitMask32::init_type(); BitMask64::init_type(); ButtonHandle::init_type(); + ButtonMap::init_type(); CPointerCallbackObject::init_type(); CachedTypedWritableReferenceCount::init_type(); CallbackData::init_type(); diff --git a/panda/src/putil/p3putil_composite1.cxx b/panda/src/putil/p3putil_composite1.cxx index f1f2f9d7ec..8c68adf9c1 100644 --- a/panda/src/putil/p3putil_composite1.cxx +++ b/panda/src/putil/p3putil_composite1.cxx @@ -10,6 +10,7 @@ #include "bitArray.cxx" #include "bitMask.cxx" #include "buttonHandle.cxx" +#include "buttonMap.cxx" #include "buttonRegistry.cxx" #include "cachedTypedWritableReferenceCount.cxx" #include "callbackData.cxx" diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index ec7c79a48b..68e60b8e83 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -19,6 +19,7 @@ #include "graphicsPipe.h" #include "keyboardButton.h" #include "mouseButton.h" +#include "buttonMap.h" #include "clockObject.h" #include "pStatTimer.h" #include "textEncoder.h" @@ -1545,8 +1546,10 @@ get_button(XKeyEvent &key_event, bool allow_shift) { // Called by get_button(), above. //////////////////////////////////////////////////////////////////// ButtonHandle x11GraphicsWindow:: -map_button(KeySym key) { +map_button(KeySym key) const { switch (key) { + case NoSymbol: + return ButtonHandle::none(); case XK_BackSpace: return KeyboardButton::backspace(); case XK_Tab: @@ -1864,7 +1867,7 @@ map_button(KeySym key) { // Description: Maps from a single X keycode to Panda's ButtonHandle. //////////////////////////////////////////////////////////////////// ButtonHandle x11GraphicsWindow:: -map_raw_button(KeyCode key) { +map_raw_button(KeyCode key) const { switch (key) { case 9: return KeyboardButton::escape(); case 10: return KeyboardButton::ascii_key('1'); @@ -2001,6 +2004,36 @@ get_mouse_button(XButtonEvent &button_event) { } } +//////////////////////////////////////////////////////////////////// +// Function: x11GraphicsWindow::get_keyboard_map +// Access: Private, Virtual +// Description: Returns a ButtonMap containing the association +// between raw buttons and virtual buttons. +//////////////////////////////////////////////////////////////////// +ButtonMap *x11GraphicsWindow:: +get_keyboard_map() const { + // NB. This could be improved by using the Xkb API. + //XkbDescPtr desc = XkbGetMap(_display, XkbAllMapComponentsMask, XkbUseCoreKbd); + ButtonMap *map = new ButtonMap; + + for (int k = 9; k <= 135; ++k) { + ButtonHandle raw_button = map_raw_button(k); + if (raw_button == ButtonHandle::none()) { + continue; + } + + KeySym sym = XKeycodeToKeysym(_display, k, 0); + ButtonHandle button = map_button(sym); + if (button == ButtonHandle::none()) { + continue; + } + + map->map_button(raw_button, button, name); + } + + return map; +} + //////////////////////////////////////////////////////////////////// // Function: x11GraphicsWindow::check_event // Access: Private, Static diff --git a/panda/src/x11display/x11GraphicsWindow.h b/panda/src/x11display/x11GraphicsWindow.h index e5f51d9cf3..e032cd7109 100644 --- a/panda/src/x11display/x11GraphicsWindow.h +++ b/panda/src/x11display/x11GraphicsWindow.h @@ -66,9 +66,10 @@ protected: void handle_keyrelease(XKeyEvent &event); ButtonHandle get_button(XKeyEvent &key_event, bool allow_shift); - ButtonHandle map_button(KeySym key); - ButtonHandle map_raw_button(KeyCode key); + ButtonHandle map_button(KeySym key) const; + ButtonHandle map_raw_button(KeyCode key) const; ButtonHandle get_mouse_button(XButtonEvent &button_event); + virtual ButtonMap *get_keyboard_map() const; static Bool check_event(X11_Display *display, XEvent *event, char *arg); From 88f1cc5347f251ceaa5056631a56dd451ee85fad Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Mar 2014 17:49:03 +0000 Subject: [PATCH 03/26] oops, fix typo --- panda/src/x11display/x11GraphicsWindow.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 68e60b8e83..80c1c884c7 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -2028,7 +2028,7 @@ get_keyboard_map() const { continue; } - map->map_button(raw_button, button, name); + map->map_button(raw_button, button); } return map; From d6be70b339414f86f57201dc3003031355f09b78 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Mar 2014 18:54:30 +0000 Subject: [PATCH 04/26] s/text/label/ --- panda/src/putil/buttonMap.I | 20 ++++++++++---------- panda/src/putil/buttonMap.cxx | 4 ++-- panda/src/putil/buttonMap.h | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/panda/src/putil/buttonMap.I b/panda/src/putil/buttonMap.I index e51b3c5a0d..9fd7f1af46 100644 --- a/panda/src/putil/buttonMap.I +++ b/panda/src/putil/buttonMap.I @@ -47,15 +47,15 @@ get_mapped_button(int i) const { } //////////////////////////////////////////////////////////////////// -// Function: ButtonMap::get_mapped_button_text +// Function: ButtonMap::get_mapped_button_label // Access: Published -// Description: Returns the text associated with the nth mapped +// Description: Returns the label associated with the nth mapped // button, meaning the button that the nth raw // button is mapped to. //////////////////////////////////////////////////////////////////// INLINE const string &ButtonMap:: -get_mapped_button_text(int i) const { - return _buttons[i]->_text; +get_mapped_button_label(int i) const { + return _buttons[i]->_label; } //////////////////////////////////////////////////////////////////// @@ -94,7 +94,7 @@ get_mapped_button(const string &raw_name) const { } //////////////////////////////////////////////////////////////////// -// Function: ButtoMap::get_mapped_button_text +// Function: ButtoMap::get_mapped_button_label // Access: Published // Description: If the button map specifies a special name for the // button (eg. if the operating system or keyboard @@ -106,19 +106,19 @@ get_mapped_button(const string &raw_name) const { // name of the Panda event associated with the button. //////////////////////////////////////////////////////////////////// INLINE const string &ButtonMap:: -get_mapped_button_text(ButtonHandle raw) const { +get_mapped_button_label(ButtonHandle raw) const { pmap::const_iterator it; it = _button_map.find(raw.get_index()); if (it == _button_map.end()) { static const string empty = ""; return empty; } else { - return it->second._text; + return it->second._label; } } //////////////////////////////////////////////////////////////////// -// Function: ButtoMap::get_mapped_button_text +// Function: ButtoMap::get_mapped_button_label // Access: Published // Description: If the button map specifies a special name for the // button (eg. if the operating system or keyboard @@ -130,12 +130,12 @@ get_mapped_button_text(ButtonHandle raw) const { // name of the Panda event associated with the button. //////////////////////////////////////////////////////////////////// INLINE const string &ButtonMap:: -get_mapped_button_text(const string &raw_name) const { +get_mapped_button_label(const string &raw_name) const { ButtonHandle raw_button = ButtonRegistry::ptr()->find_button(raw_name); if (raw_button == ButtonHandle::none()) { static const string empty = ""; return empty; } else { - return get_mapped_button_text(raw_button); + return get_mapped_button_label(raw_button); } } diff --git a/panda/src/putil/buttonMap.cxx b/panda/src/putil/buttonMap.cxx index 1452b4542c..8497a04ed4 100644 --- a/panda/src/putil/buttonMap.cxx +++ b/panda/src/putil/buttonMap.cxx @@ -22,12 +22,12 @@ TypeHandle ButtonMap::_type_handle; // Description: Registers a new button mapping. //////////////////////////////////////////////////////////////////// void ButtonMap:: -map_button(ButtonHandle raw_button, ButtonHandle button, const string &text) { +map_button(ButtonHandle raw_button, ButtonHandle button, const string &label) { int index = raw_button.get_index(); ButtonNode bnode; bnode._raw = raw_button; bnode._mapped = button; - bnode._text = text; + bnode._label = label; _button_map[index] = bnode; _buttons.push_back(&_button_map[index]); } diff --git a/panda/src/putil/buttonMap.h b/panda/src/putil/buttonMap.h index a6ca416071..1140e9a16e 100644 --- a/panda/src/putil/buttonMap.h +++ b/panda/src/putil/buttonMap.h @@ -35,21 +35,21 @@ PUBLISHED: INLINE int get_num_buttons() const; INLINE ButtonHandle get_raw_button(int i) const; INLINE ButtonHandle get_mapped_button(int i) const; - INLINE const string &get_mapped_button_text(int i) const; + INLINE const string &get_mapped_button_label(int i) const; INLINE ButtonHandle get_mapped_button(ButtonHandle raw) const; INLINE ButtonHandle get_mapped_button(const string &raw_name) const; - INLINE const string &get_mapped_button_text(ButtonHandle raw) const; - INLINE const string &get_mapped_button_text(const string &raw_name) const; + INLINE const string &get_mapped_button_label(ButtonHandle raw) const; + INLINE const string &get_mapped_button_label(const string &raw_name) const; public: - void map_button(ButtonHandle raw_button, ButtonHandle button, const string &text = ""); + void map_button(ButtonHandle raw_button, ButtonHandle button, const string &label = ""); private: struct ButtonNode { ButtonHandle _raw; - ButtonHandle _mapped; - string _text; + ButtonHandle _mapped; + string _label; }; pmap _button_map; From 356012246ea91e0309a3343c915036bb65b191c0 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 10 Mar 2014 12:24:03 +0000 Subject: [PATCH 05/26] Implement win.get_keyboard_map() on Windows --- panda/src/putil/buttonMap.cxx | 5 ++ panda/src/putil/buttonMap.h | 2 +- panda/src/windisplay/winGraphicsWindow.cxx | 77 ++++++++++++++++++++-- panda/src/windisplay/winGraphicsWindow.h | 1 + 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/panda/src/putil/buttonMap.cxx b/panda/src/putil/buttonMap.cxx index 8497a04ed4..9d890233e1 100644 --- a/panda/src/putil/buttonMap.cxx +++ b/panda/src/putil/buttonMap.cxx @@ -24,6 +24,11 @@ TypeHandle ButtonMap::_type_handle; void ButtonMap:: map_button(ButtonHandle raw_button, ButtonHandle button, const string &label) { int index = raw_button.get_index(); + if (_button_map.find(index) != _button_map.end()) { + // A button with this index was already mapped. + return; + } + ButtonNode bnode; bnode._raw = raw_button; bnode._mapped = button; diff --git a/panda/src/putil/buttonMap.h b/panda/src/putil/buttonMap.h index 1140e9a16e..9b6e765e62 100644 --- a/panda/src/putil/buttonMap.h +++ b/panda/src/putil/buttonMap.h @@ -30,7 +30,7 @@ // button, which may optionally be associated with an // appropriate platform-specific name for the button. //////////////////////////////////////////////////////////////////// -class ButtonMap : public TypedReferenceCount { +class EXPCL_PANDA_PUTIL ButtonMap : public TypedReferenceCount { PUBLISHED: INLINE int get_num_buttons() const; INLINE ButtonHandle get_raw_button(int i) const; diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 25090a7069..c3bddb7d1b 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -735,9 +735,9 @@ handle_reshape() { return; } - bool result = ClientToScreen(_hWnd, (POINT*)&view_rect.left); // translates top,left pnt + bool result = (FALSE != ClientToScreen(_hWnd, (POINT*)&view_rect.left)); // translates top,left pnt if (result) { - result = ClientToScreen(_hWnd, (POINT*)&view_rect.right); // translates right,bottom pnt + result = (FALSE != ClientToScreen(_hWnd, (POINT*)&view_rect.right)); // translates right,bottom pnt } if (!result) { @@ -2495,7 +2495,10 @@ lookup_raw_key(LPARAM lparam) const { if (lparam & 0x1000000) { // Extended keys switch (vsc) { + case 28: return KeyboardButton::enter(); case 29: return KeyboardButton::rcontrol(); + case 53: return KeyboardButton::ascii_key('/'); + case 55: return KeyboardButton::print_screen(); case 56: return KeyboardButton::ralt(); case 69: return KeyboardButton::num_lock(); case 71: return KeyboardButton::home(); @@ -2508,6 +2511,9 @@ lookup_raw_key(LPARAM lparam) const { case 81: return KeyboardButton::page_down(); case 82: return KeyboardButton::insert(); case 83: return KeyboardButton::del(); + case 91: return KeyboardButton::lmeta(); + case 92: return KeyboardButton::rmeta(); + case 93: return KeyboardButton::menu(); } } @@ -2605,13 +2611,74 @@ lookup_raw_key(LPARAM lparam) const { switch (vsc) { case 87: return KeyboardButton::f11(); case 88: return KeyboardButton::f12(); - case 91: return KeyboardButton::lmeta(); - case 92: return KeyboardButton::rmeta(); - case 93: return KeyboardButton::menu(); default: return ButtonHandle::none(); } } +//////////////////////////////////////////////////////////////////// +// Function: WinGraphicsWindow::get_keyboard_map +// Access: Published, Virtual +// Description: Returns a ButtonMap containing the association +// between raw buttons and virtual buttons. +// +// Note that on Windows, the pause button and numpad +// keys are not mapped reliably. +//////////////////////////////////////////////////////////////////// +ButtonMap *WinGraphicsWindow:: +get_keyboard_map() const { + ButtonMap *map = new ButtonMap; + + char text[256]; + UINT vsc = 0; + unsigned short ex_vsc[] = {0x57, 0x58, + 0x011c, 0x011d, 0x0135, 0x0137, 0x0138, 0x0145, 0x0147, 0x0148, 0x0149, 0x014b, 0x014d, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x015b, 0x015c, 0x015d}; + + for (int k = 1; k < 84 + 17; ++k) { + if (k >= 84) { + vsc = ex_vsc[k - 84]; + } else { + vsc = k; + } + + UINT lparam = vsc << 16; + ButtonHandle raw_button = lookup_raw_key(lparam); + if (raw_button == ButtonHandle::none()) { + continue; + } + + ButtonHandle button; + if (vsc == 0x45) { + button = KeyboardButton::pause(); + + } else if (vsc >= 0x47 && vsc <= 0x53) { + // The numpad keys are not mapped correctly, see KB72583 + button = raw_button; + + } else { + if (vsc == 0x145) { + // Don't ask why - I have no idea. + vsc = 0x45; + } + if (vsc & 0x0100) { + // MapVirtualKey recognizes extended codes differently. + vsc ^= 0xe100; + } + + UINT vk = MapVirtualKeyA(vsc, MAPVK_VSC_TO_VK_EX); + button = lookup_key(vk); + if (button == ButtonHandle::none()) { + continue; + } + } + + int len = GetKeyNameTextA(lparam, text, 256); + string label (text, len); + map->map_button(raw_button, button, label); + } + + return map; +} + //////////////////////////////////////////////////////////////////// // Function: WinGraphicsWindow::handle_raw_input // Access: Private diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 8519a3034c..a8fe6bd8cd 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -135,6 +135,7 @@ private: void handle_raw_keyrelease(ButtonHandle key, double time); ButtonHandle lookup_key(WPARAM wparam) const; ButtonHandle lookup_raw_key(LPARAM lparam) const; + virtual ButtonMap *get_keyboard_map() const; INLINE int translate_mouse(int pos) const; INLINE void set_cursor_in_window(); INLINE void set_cursor_out_of_window(); From 25ee1ce2851c6039e7fec04155a3d95227e30778 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 13 Mar 2014 23:15:19 +0000 Subject: [PATCH 06/26] fix compilation issue with ppremake --- panda/src/egg/p3egg_composite1.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/panda/src/egg/p3egg_composite1.cxx b/panda/src/egg/p3egg_composite1.cxx index 961b702a28..e0dd93555d 100644 --- a/panda/src/egg/p3egg_composite1.cxx +++ b/panda/src/egg/p3egg_composite1.cxx @@ -13,6 +13,7 @@ #include "eggFilenameNode.cxx" #include "eggGroup.cxx" #include "eggGroupNode.cxx" +#include "eggGroupNode_ext.cxx" #include "eggGroupUniquifier.cxx" #include "eggLine.cxx" #include "eggMaterial.cxx" From dbc6091cf074ad3ee072adb900446bbe69612133 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 13 Mar 2014 23:16:21 +0000 Subject: [PATCH 07/26] add PfmVizzer::set_aux_pfm() and PfmFile::set_no_data_threshold() --- panda/src/grutil/pfmVizzer.I | 47 ++++++++++++++- panda/src/grutil/pfmVizzer.cxx | 79 +++++++++++++++++++++++- panda/src/grutil/pfmVizzer.h | 9 +++ panda/src/pnmimage/pfmFile.I | 25 ++++++++ panda/src/pnmimage/pfmFile.cxx | 107 +++++++++++++++++++++++++++++++++ panda/src/pnmimage/pfmFile.h | 8 +++ 6 files changed, 272 insertions(+), 3 deletions(-) diff --git a/panda/src/grutil/pfmVizzer.I b/panda/src/grutil/pfmVizzer.I index 26446a257f..d392379ecb 100644 --- a/panda/src/grutil/pfmVizzer.I +++ b/panda/src/grutil/pfmVizzer.I @@ -17,7 +17,7 @@ // Function: PfmVizzer::get_pfm // Access: Published // Description: Returns the reference to the PfmFile manipulated by -// thiz PfmVizzer. +// this PfmVizzer. //////////////////////////////////////////////////////////////////// INLINE PfmFile &PfmVizzer:: get_pfm() { @@ -28,7 +28,7 @@ get_pfm() { // Function: PfmVizzer::get_pfm // Access: Published // Description: Returns the reference to the PfmFile manipulated by -// thiz PfmVizzer. +// this PfmVizzer. //////////////////////////////////////////////////////////////////// INLINE const PfmFile &PfmVizzer:: get_pfm() const { @@ -206,6 +206,49 @@ get_vis_blend() const { return _vis_blend; } +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::set_aux_pfm +// Access: Published +// Description: Assigns an auxiliary PfmFile to this PfmVizzer. This +// file will be queried by column types +// CT_aux_vertex1/2/3, but has no other meaning to the +// vizzer. This size of this PfmFile should exactly +// match the base PfmFile. No reference count is held +// and no copy is made; the caller is responsible for +// ensuring that the auxiliary PfmFile will persist +// throughout the lifetime of the PfmVizzer it is +// assigned to. +//////////////////////////////////////////////////////////////////// +INLINE void PfmVizzer:: +set_aux_pfm(const PfmFile *pfm) { + assert(pfm == NULL || (pfm->get_x_size() == _pfm.get_x_size() && + pfm->get_y_size() == _pfm.get_y_size())); + _aux_pfm = pfm; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::clear_aux_pfm +// Access: Published +// Description: Removes the auxiliary PfmFile from this PfmVizzer. +//////////////////////////////////////////////////////////////////// +INLINE void PfmVizzer:: +clear_aux_pfm() { + _aux_pfm = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::get_aux_pfm +// Access: Published +// Description: Returns the reference to the auxiliary PfmFile +// queried by this PfmVizzer. This contains the values +// that will be reflected in CT_aux_vertex3 etc. See +// set_aux_pfm(). +//////////////////////////////////////////////////////////////////// +INLINE const PfmFile *PfmVizzer:: +get_aux_pfm() const { + return _aux_pfm; +} + //////////////////////////////////////////////////////////////////// // Function: PfmVizzer::VisColumn::Constructor // Access: Public diff --git a/panda/src/grutil/pfmVizzer.cxx b/panda/src/grutil/pfmVizzer.cxx index 3033af5845..dfd0f50399 100644 --- a/panda/src/grutil/pfmVizzer.cxx +++ b/panda/src/grutil/pfmVizzer.cxx @@ -38,6 +38,7 @@ PfmVizzer(PfmFile &pfm) : _pfm(pfm) { _vis_2d = false; _keep_beyond_lens = false; _vis_blend = NULL; + _aux_pfm = NULL; } //////////////////////////////////////////////////////////////////// @@ -253,6 +254,9 @@ NodePath PfmVizzer:: generate_vis_points() const { nassertr(_pfm.is_valid(), NodePath()); + bool check_aux_pfm = uses_aux_pfm(); + nassertr(!check_aux_pfm || (_aux_pfm != NULL && _aux_pfm->is_valid()), NodePath()); + CPT(GeomVertexFormat) format; if (_vis_inverse) { if (_vis_2d) { @@ -291,6 +295,9 @@ generate_vis_points() const { if (!_pfm.has_point(xi, yi)) { continue; } + if (check_aux_pfm && !_aux_pfm->has_point(xi, yi)) { + continue; + } const LPoint3f &point = _pfm.get_point(xi, yi); LPoint2f uv((PN_float32(xi) + 0.5) * uv_scale[0], @@ -330,6 +337,8 @@ generate_vis_points() const { NodePath PfmVizzer:: generate_vis_mesh(MeshFace face) const { nassertr(_pfm.is_valid(), NodePath()); + bool check_aux_pfm = uses_aux_pfm(); + nassertr(!check_aux_pfm || (_aux_pfm != NULL && _aux_pfm->is_valid()), NodePath()); nassertr(face != 0, NodePath()); if (_pfm.get_num_channels() == 1 && _vis_columns.empty()) { @@ -512,6 +521,31 @@ make_displacement(PNMImage &result, double max_u, double max_v) const { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::uses_aux_pfm +// Access: Private +// Description: Returns true if any of the vis_column tokens +// reference the aux_pfm file, false otherwise. +//////////////////////////////////////////////////////////////////// +bool PfmVizzer:: +uses_aux_pfm() const { + for (VisColumns::const_iterator vci = _vis_columns.begin(); + vci != _vis_columns.end(); + ++vci) { + const VisColumn &column = *vci; + switch (column._source) { + case CT_aux_vertex1: + case CT_aux_vertex2: + case CT_aux_vertex3: + return true; + default: + break; + } + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PfmVizzer::r_fill_displacement // Access: Private @@ -616,6 +650,7 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { if (vis_columns.empty()) { build_auto_vis_columns(vis_columns, true); } + bool check_aux_pfm = uses_aux_pfm(); CPT(GeomVertexFormat) format = make_array_format(vis_columns); @@ -685,7 +720,13 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { !_pfm.has_point(xi + 1, yi)) { continue; } - + if (check_aux_pfm && (!_aux_pfm->has_point(xi, yi) || + !_aux_pfm->has_point(xi, yi + 1) || + !_aux_pfm->has_point(xi + 1, yi + 1) || + !_aux_pfm->has_point(xi + 1, yi))) { + continue; + } + if (!keep_beyond_lens && (skip_points[(yi - y_begin) * x_size + (xi - x_begin)] || skip_points[(yi - y_begin + 1) * x_size + (xi - x_begin)] || @@ -833,18 +874,21 @@ make_array_format(const VisColumns &vis_columns) const { break; case CT_vertex1: + case CT_aux_vertex1: num_components = 1; numeric_type = GeomEnums::NT_float32; contents = GeomEnums::C_point; break; case CT_vertex2: + case CT_aux_vertex2: num_components = 2; numeric_type = GeomEnums::NT_float32; contents = GeomEnums::C_point; break; case CT_vertex3: + case CT_aux_vertex3: num_components = 3; numeric_type = GeomEnums::NT_float32; contents = GeomEnums::C_point; @@ -917,6 +961,18 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo } break; + case CT_aux_vertex1: + { + nassertr(vizzer.get_aux_pfm() != NULL, false); + PN_float32 p = vizzer.get_aux_pfm()->get_point1(xi, yi); + LPoint2f point(p, 0.0); + if (!transform_point(point)) { + success = false; + } + vwriter.set_data2f(point); + } + break; + case CT_vertex2: { LPoint2f point = pfm.get_point2(xi, yi); @@ -927,6 +983,17 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo } break; + case CT_aux_vertex2: + { + nassertr(vizzer.get_aux_pfm() != NULL, false); + LPoint2f point = vizzer.get_aux_pfm()->get_point2(xi, yi); + if (!transform_point(point)) { + success = false; + } + vwriter.set_data2f(point); + } + break; + case CT_vertex3: { LPoint3f point = pfm.get_point(xi, yi); @@ -937,6 +1004,16 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo } break; + case CT_aux_vertex3: + { + LPoint3f point = vizzer.get_aux_pfm()->get_point(xi, yi); + if (!transform_point(point)) { + success = false; + } + vwriter.set_data3f(point); + } + break; + case CT_normal3: { // Calculate the normal based on two neighboring vertices. diff --git a/panda/src/grutil/pfmVizzer.h b/panda/src/grutil/pfmVizzer.h index 551606755e..2d20b4d1d6 100644 --- a/panda/src/grutil/pfmVizzer.h +++ b/panda/src/grutil/pfmVizzer.h @@ -53,6 +53,10 @@ PUBLISHED: INLINE void clear_vis_blend(); INLINE const PNMImage *get_vis_blend() const; + INLINE void set_aux_pfm(const PfmFile *pfm); + INLINE void clear_aux_pfm(); + INLINE const PfmFile *get_aux_pfm() const; + enum ColumnType { CT_texcoord2, CT_texcoord3, @@ -61,6 +65,9 @@ PUBLISHED: CT_vertex3, CT_normal3, CT_blend1, + CT_aux_vertex1, + CT_aux_vertex2, + CT_aux_vertex3, }; void clear_vis_columns(); void add_vis_column(ColumnType source, ColumnType target, @@ -82,6 +89,7 @@ PUBLISHED: BLOCKING void make_displacement(PNMImage &result, double max_u, double max_v) const; private: + bool uses_aux_pfm() const; void r_fill_displacement(PNMImage &result, int xi, int yi, double nxi, double nyi, double u_scale, double v_scale, int distance) const; @@ -117,6 +125,7 @@ private: private: PfmFile &_pfm; + const PfmFile *_aux_pfm; bool _vis_inverse; PT(InternalName) _flat_texcoord_name; diff --git a/panda/src/pnmimage/pfmFile.I b/panda/src/pnmimage/pfmFile.I index d53bd44523..928677ca65 100644 --- a/panda/src/pnmimage/pfmFile.I +++ b/panda/src/pnmimage/pfmFile.I @@ -478,6 +478,7 @@ INLINE void PfmFile:: set_no_data_chan4(bool chan4) { if (chan4 && _num_channels == 4) { _has_no_data_value = true; + _has_no_data_threshold = false; _no_data_value.set(0.0, 0.0, 0.0, -1.0); _has_point = has_point_chan4; } else { @@ -496,6 +497,18 @@ set_no_data_value(const LPoint4d &no_data_value) { set_no_data_value(LCAST(PN_float32, no_data_value)); } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::set_no_data_threshold +// Access: Published +// Description: Sets the special threshold value. Points that are +// below this value in all components are considered "no +// value". +//////////////////////////////////////////////////////////////////// +INLINE void PfmFile:: +set_no_data_threshold(const LPoint4d &no_data_threshold) { + set_no_data_threshold(LCAST(PN_float32, no_data_threshold)); +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::set_no_data_value // Access: Published @@ -506,6 +519,7 @@ set_no_data_value(const LPoint4d &no_data_value) { INLINE void PfmFile:: clear_no_data_value() { _has_no_data_value = false; + _has_no_data_threshold = false; _no_data_value = LPoint4f::zero(); _has_point = has_point_noop; } @@ -521,6 +535,17 @@ has_no_data_value() const { return _has_no_data_value; } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_no_data_threshold +// Access: Published +// Description: Returns whether a "no data" threshold value has been +// established by set_no_data_threshold(). +//////////////////////////////////////////////////////////////////// +INLINE bool PfmFile:: +has_no_data_threshold() const { + return _has_no_data_threshold; +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::get_no_data_value // Access: Published diff --git a/panda/src/pnmimage/pfmFile.cxx b/panda/src/pnmimage/pfmFile.cxx index 06e13106bd..bae7793e45 100644 --- a/panda/src/pnmimage/pfmFile.cxx +++ b/panda/src/pnmimage/pfmFile.cxx @@ -33,6 +33,7 @@ PfmFile:: PfmFile() { _has_no_data_value = false; + _has_no_data_threshold = false; _no_data_value = LPoint4f::zero(); _has_point = has_point_noop; clear(); @@ -49,6 +50,7 @@ PfmFile(const PfmFile ©) : _table(copy._table), _scale(copy._scale), _has_no_data_value(copy._has_no_data_value), + _has_no_data_threshold(copy._has_no_data_threshold), _no_data_value(copy._no_data_value), _has_point(copy._has_point) { @@ -65,6 +67,7 @@ operator = (const PfmFile ©) { _table = copy._table; _scale = copy._scale; _has_no_data_value = copy._has_no_data_value; + _has_no_data_threshold = copy._has_no_data_threshold; _no_data_value = copy._no_data_value; _has_point = copy._has_point; } @@ -908,6 +911,7 @@ set_no_data_nan(int num_channels) { if (num_channels > 0) { num_channels = min(num_channels, _num_channels); _has_no_data_value = true; + _has_no_data_threshold = false; _no_data_value = LPoint4f::zero(); PN_float32 nan = make_nan((PN_float32)0.0); for (int i = 0; i < num_channels; ++i) { @@ -945,6 +949,7 @@ set_no_data_value(const LPoint4f &no_data_value) { nassertv(is_valid()); _has_no_data_value = true; + _has_no_data_threshold = false; _no_data_value = no_data_value; switch (_num_channels) { case 1: @@ -964,6 +969,38 @@ set_no_data_value(const LPoint4f &no_data_value) { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::set_no_data_threshold +// Access: Published +// Description: Sets the special threshold value. Points that are +// below this value in all components are considered "no +// value". +//////////////////////////////////////////////////////////////////// +void PfmFile:: +set_no_data_threshold(const LPoint4f &no_data_value) { + nassertv(is_valid()); + + _has_no_data_value = true; + _has_no_data_threshold = true; + _no_data_value = no_data_value; + switch (_num_channels) { + case 1: + _has_point = has_point_threshold_1; + break; + case 2: + _has_point = has_point_threshold_2; + break; + case 3: + _has_point = has_point_threshold_3; + break; + case 4: + _has_point = has_point_threshold_4; + break; + default: + nassertv(false); + } +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::resize // Access: Published @@ -2395,6 +2432,76 @@ has_point_4(const PfmFile *self, int x, int y) { return false; } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_1 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 1-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_1(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x)]; + return table[0] >= self->_no_data_value[0]; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_2 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 2-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_2(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x) * 2]; + return (table[0] >= self->_no_data_value[0] || + table[1] >= self->_no_data_value[1]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_3 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 3-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_3(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x) * 3]; + return (table[0] >= self->_no_data_value[0] || + table[1] >= self->_no_data_value[1] || + table[2] >= self->_no_data_value[2]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_4 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 4-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_4(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x) * 4]; + return (table[0] >= self->_no_data_value[0] || + table[1] >= self->_no_data_value[1] || + table[2] >= self->_no_data_value[2] || + table[3] >= self->_no_data_value[3]); + } + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::has_point_chan4 // Access: Private, Static diff --git a/panda/src/pnmimage/pfmFile.h b/panda/src/pnmimage/pfmFile.h index 7f22ef79c0..3cf0a5d1c0 100644 --- a/panda/src/pnmimage/pfmFile.h +++ b/panda/src/pnmimage/pfmFile.h @@ -104,8 +104,11 @@ PUBLISHED: void set_no_data_nan(int num_channels); void set_no_data_value(const LPoint4f &no_data_value); INLINE void set_no_data_value(const LPoint4d &no_data_value); + void set_no_data_threshold(const LPoint4f &no_data_value); + INLINE void set_no_data_threshold(const LPoint4d &no_data_value); INLINE void clear_no_data_value(); INLINE bool has_no_data_value() const; + INLINE bool has_no_data_threshold() const; INLINE const LPoint4f &get_no_data_value() const; BLOCKING void resize(int new_x_size, int new_y_size); @@ -195,6 +198,10 @@ private: static bool has_point_2(const PfmFile *file, int x, int y); static bool has_point_3(const PfmFile *file, int x, int y); static bool has_point_4(const PfmFile *file, int x, int y); + static bool has_point_threshold_1(const PfmFile *file, int x, int y); + static bool has_point_threshold_2(const PfmFile *file, int x, int y); + static bool has_point_threshold_3(const PfmFile *file, int x, int y); + static bool has_point_threshold_4(const PfmFile *file, int x, int y); static bool has_point_chan4(const PfmFile *file, int x, int y); static bool has_point_nan_1(const PfmFile *file, int x, int y); static bool has_point_nan_2(const PfmFile *file, int x, int y); @@ -208,6 +215,7 @@ private: PN_float32 _scale; bool _has_no_data_value; + bool _has_no_data_threshold; LPoint4f _no_data_value; typedef bool HasPointFunc(const PfmFile *file, int x, int y); From e9ec2cbf783e9d33de1a4447a97fe0efbc6508b4 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 17 Mar 2014 09:41:04 +0000 Subject: [PATCH 08/26] Implement get_keyboard_map on Mac OS X --- panda/src/cocoadisplay/cocoaGraphicsWindow.h | 5 +- panda/src/cocoadisplay/cocoaGraphicsWindow.mm | 76 +++++++++++++++++-- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.h b/panda/src/cocoadisplay/cocoaGraphicsWindow.h index b50edbf173..a7c44036e6 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.h +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.h @@ -58,6 +58,7 @@ public: void handle_mouse_button_event(int button, bool down); void handle_mouse_moved_event(bool in_window, double x, double y, bool absolute); void handle_wheel_event(double x, double y); + virtual ButtonMap *get_keyboard_map() const; INLINE NSWindow *get_nswindow() const; INLINE NSView *get_nsview() const; @@ -81,8 +82,8 @@ private: NSImage *load_image(const Filename &filename); void handle_modifier(NSUInteger modifierFlags, NSUInteger mask, ButtonHandle button); - ButtonHandle map_key(unsigned short c); - ButtonHandle map_raw_key(unsigned short keycode); + ButtonHandle map_key(unsigned short c) const; + ButtonHandle map_raw_key(unsigned short keycode) const; private: NSWindow *_window; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index a5c63f3d50..5494e30d8e 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -39,7 +39,7 @@ #import #import #import -//#import +#import TypeHandle CocoaGraphicsWindow::_type_handle; @@ -1730,13 +1730,70 @@ handle_wheel_event(double x, double y) { } } +//////////////////////////////////////////////////////////////////// +// Function: CocoaGraphicsWindow::get_keyboard_map +// Access: Published, Virtual +// Description: Returns a ButtonMap containing the association +// between raw buttons and virtual buttons. +//////////////////////////////////////////////////////////////////// +ButtonMap *CocoaGraphicsWindow:: +get_keyboard_map() const { + TISInputSourceRef input_source; + CFDataRef layout_data; + const UCKeyboardLayout *layout; + + // Get the current keyboard layout data. + input_source = TISCopyCurrentKeyboardInputSource(); + layout_data = (CFDataRef) TISGetInputSourceProperty(input_source, kTISPropertyUnicodeKeyLayoutData); + layout = (const UCKeyboardLayout *)CFDataGetBytePtr(layout_data); + + ButtonMap *map = new ButtonMap; + + UniChar chars[4]; + UniCharCount num_chars; + + // Iterate through the known scancode range and see what + // every scan code is mapped to. + for (int k = 0; k <= 0x7E; ++k) { + ButtonHandle raw_button = map_raw_key(k); + if (raw_button == ButtonHandle::none()) { + continue; + } + + UInt32 dead_keys = 0; + if (UCKeyTranslate(layout, k, kUCKeyActionDisplay, 0, LMGetKbdType(), + kUCKeyTranslateNoDeadKeysMask, &dead_keys, 4, + &num_chars, chars) == noErr) { + if (num_chars > 0 && chars[0] != 0x10) { + ButtonHandle button = ButtonHandle::none(); + + if (chars[0] > 0 && chars[0] <= 0x7f) { + button = KeyboardButton::ascii_key(chars[0]); + } + if (button == ButtonHandle::none()) { + button = map_key(chars[0]); + } + if (button != ButtonHandle::none()) { + map->map_button(raw_button, button); + } + } else { + // A special function key or modifier key, which isn't remapped by the OS. + map->map_button(raw_button, raw_button); + } + } + } + + CFRelease(input_source); + return map; +} + //////////////////////////////////////////////////////////////////// // Function: CocoaGraphicsWindow::map_key // Access: Private -// Description: Maps a Cocoa key character to a ButtonHandle. +// Description: Maps a unicode key character to a ButtonHandle. //////////////////////////////////////////////////////////////////// ButtonHandle CocoaGraphicsWindow:: -map_key(unsigned short c) { +map_key(unsigned short c) const { switch (c) { case NSEnterCharacter: return KeyboardButton::enter(); @@ -1749,17 +1806,21 @@ map_key(unsigned short c) { // BackTabCharacter is sent when shift-tab is used. return KeyboardButton::tab(); - case 16: + case 0x10: // No idea where this constant comes from, but it // is sent whenever the menu key is pressed. return KeyboardButton::menu(); + case 0x1e: case NSUpArrowFunctionKey: return KeyboardButton::up(); + case 0x1f: case NSDownArrowFunctionKey: return KeyboardButton::down(); + case 0x1c: case NSLeftArrowFunctionKey: return KeyboardButton::left(); + case 0x1d: case NSRightArrowFunctionKey: return KeyboardButton::right(); case NSF1FunctionKey: @@ -1818,14 +1879,18 @@ map_key(unsigned short c) { return KeyboardButton::insert(); case NSDeleteFunctionKey: return KeyboardButton::del(); + case 0x01: case NSHomeFunctionKey: return KeyboardButton::home(); case NSBeginFunctionKey: break; + case 0x04: case NSEndFunctionKey: return KeyboardButton::end(); + case 0x0b: case NSPageUpFunctionKey: return KeyboardButton::page_up(); + case 0x0c: case NSPageDownFunctionKey: return KeyboardButton::page_down(); case NSPrintScreenFunctionKey: @@ -1858,6 +1923,7 @@ map_key(unsigned short c) { case NSRedoFunctionKey: case NSFindFunctionKey: break; + case 0x05: case NSHelpFunctionKey: return KeyboardButton::help(); case NSModeSwitchFunctionKey: @@ -1872,7 +1938,7 @@ map_key(unsigned short c) { // Description: Maps a keycode to a ButtonHandle. //////////////////////////////////////////////////////////////////// ButtonHandle CocoaGraphicsWindow:: -map_raw_key(unsigned short keycode) { +map_raw_key(unsigned short keycode) const { if (keycode > 0x7f) { return ButtonHandle::none(); } From fd09dc0ab2a1dcff3075c4562359011f28914fe3 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 17 Mar 2014 09:58:15 +0000 Subject: [PATCH 09/26] Add output() and write() to ButtonMap --- panda/src/putil/buttonMap.cxx | 29 +++++++++++++++++++++++++++++ panda/src/putil/buttonMap.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/panda/src/putil/buttonMap.cxx b/panda/src/putil/buttonMap.cxx index 9d890233e1..40f609760c 100644 --- a/panda/src/putil/buttonMap.cxx +++ b/panda/src/putil/buttonMap.cxx @@ -36,3 +36,32 @@ map_button(ButtonHandle raw_button, ButtonHandle button, const string &label) { _button_map[index] = bnode; _buttons.push_back(&_button_map[index]); } + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::output +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void ButtonMap:: +output(ostream &out) const { + out << "ButtonMap (" << get_num_buttons() << " buttons)"; +} + +//////////////////////////////////////////////////////////////////// +// Function: ButtonMap::write +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void ButtonMap:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "ButtonMap, " << get_num_buttons() << " buttons:\n"; + + pvector::const_iterator it; + for (it = _buttons.begin(); it != _buttons.end(); ++it) { + const ButtonNode *bn = *it; + + indent(out, indent_level + 2) + << bn->_raw << " -> " << bn->_mapped << " \"" << bn->_label << "\"\n"; + } +} diff --git a/panda/src/putil/buttonMap.h b/panda/src/putil/buttonMap.h index 9b6e765e62..4959a45265 100644 --- a/panda/src/putil/buttonMap.h +++ b/panda/src/putil/buttonMap.h @@ -42,6 +42,9 @@ PUBLISHED: INLINE const string &get_mapped_button_label(ButtonHandle raw) const; INLINE const string &get_mapped_button_label(const string &raw_name) const; + void output(ostream &out) const; + void write(ostream &out, int indent_level = 0) const; + public: void map_button(ButtonHandle raw_button, ButtonHandle button, const string &label = ""); From e02d8706f3cb21ee23a618a54471075fa299173a Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 17 Mar 2014 10:12:26 +0000 Subject: [PATCH 10/26] Fix EggGroupNode compilation. _ext.cxx sources should not be added to the standard composite files. --- panda/src/egg/Sources.pp | 4 ++-- panda/src/egg/eggGroupNode_ext.cxx | 2 ++ panda/src/egg/p3egg_composite1.cxx | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/panda/src/egg/Sources.pp b/panda/src/egg/Sources.pp index cc68e22b52..ed5b938e4e 100644 --- a/panda/src/egg/Sources.pp +++ b/panda/src/egg/Sources.pp @@ -24,7 +24,7 @@ eggCurve.I eggCurve.h eggData.I eggData.h \ eggExternalReference.I eggExternalReference.h \ eggFilenameNode.I eggFilenameNode.h eggGroup.I eggGroup.h \ - eggGroupNode_ext.h \ + eggGroupNode_ext.cxx eggGroupNode_ext.h \ eggGroupNode.I eggGroupNode.h eggGroupUniquifier.h \ eggLine.I eggLine.h \ eggMaterial.I eggMaterial.h eggMaterialCollection.I \ @@ -71,7 +71,7 @@ eggCoordinateSystem.cxx \ eggCurve.cxx eggData.cxx eggExternalReference.cxx \ eggFilenameNode.cxx eggGroup.cxx \ - eggGroupNode_ext.cxx eggGroupNode.cxx \ + eggGroupNode.cxx \ eggGroupUniquifier.cxx eggLine.cxx eggMaterial.cxx \ eggMaterialCollection.cxx \ eggMesher.cxx \ diff --git a/panda/src/egg/eggGroupNode_ext.cxx b/panda/src/egg/eggGroupNode_ext.cxx index 457ea73ba3..e554bb243c 100644 --- a/panda/src/egg/eggGroupNode_ext.cxx +++ b/panda/src/egg/eggGroupNode_ext.cxx @@ -16,7 +16,9 @@ #ifdef HAVE_PYTHON +#ifndef CPPPARSER IMPORT_THIS struct Dtool_PyTypedObject Dtool_EggNode; +#endif //////////////////////////////////////////////////////////////////// // Function: EggGroupNode::get_children diff --git a/panda/src/egg/p3egg_composite1.cxx b/panda/src/egg/p3egg_composite1.cxx index e0dd93555d..961b702a28 100644 --- a/panda/src/egg/p3egg_composite1.cxx +++ b/panda/src/egg/p3egg_composite1.cxx @@ -13,7 +13,6 @@ #include "eggFilenameNode.cxx" #include "eggGroup.cxx" #include "eggGroupNode.cxx" -#include "eggGroupNode_ext.cxx" #include "eggGroupUniquifier.cxx" #include "eggLine.cxx" #include "eggMaterial.cxx" From 8ae5e58d92542ab395949ae26a582b41cb44fbc1 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 17 Mar 2014 13:26:58 +0000 Subject: [PATCH 11/26] Preserve symlinks when copying files --- makepanda/makepandacore.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 0c760d30a0..ec7e661d21 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2333,8 +2333,12 @@ def CopyFile(dstfile, srcfile): if (fnl < 0): fn = srcfile else: fn = srcfile[fnl+1:] dstfile = dstdir + fn - if (NeedsBuild([dstfile], [srcfile])): - WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) + if NeedsBuild([dstfile], [srcfile]): + if os.path.islink(srcfile): + # Preserve symlinks + os.symlink(os.readlink(srcfile), dstfile) + else: + WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) JustBuilt([dstfile], [srcfile]) def CopyAllFiles(dstdir, srcdir, suffix=""): From 32ad6785f281df2b0e260d85ee1ec7ada5b2f9b0 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 18 Mar 2014 08:24:52 +0000 Subject: [PATCH 12/26] Missing HAVE_PYTHON --- panda/src/rocket/rocketRegion_ext.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/panda/src/rocket/rocketRegion_ext.cxx b/panda/src/rocket/rocketRegion_ext.cxx index 4615854768..06791ded82 100644 --- a/panda/src/rocket/rocketRegion_ext.cxx +++ b/panda/src/rocket/rocketRegion_ext.cxx @@ -15,6 +15,8 @@ #include "rocketRegion_ext.h" #include "extension.h" +#ifdef HAVE_PYTHON + #ifndef CPPPARSER #define HAVE_LONG_LONG 1 #include @@ -48,3 +50,5 @@ get_context() const { } return NULL; } + +#endif From 528a607f4ae229288727fafc943b7814f37fc7d9 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 20 Mar 2014 22:56:53 +0000 Subject: [PATCH 13/26] Add FrameBufferProperties argument to WindowFramework --- panda/src/framework/windowFramework.cxx | 8 ++++---- panda/src/framework/windowFramework.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index 1d48b829d4..3cc0cc1f76 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -145,7 +145,8 @@ WindowFramework:: //////////////////////////////////////////////////////////////////// GraphicsOutput *WindowFramework:: open_window(const WindowProperties &props, int flags, GraphicsEngine *engine, - GraphicsPipe *pipe, GraphicsStateGuardian *gsg) { + GraphicsPipe *pipe, GraphicsStateGuardian *gsg, + const FrameBufferProperties &fbprops) { nassertr(_window == (GraphicsOutput *)NULL, _window); static int next_window_index = 1; @@ -155,9 +156,8 @@ open_window(const WindowProperties &props, int flags, GraphicsEngine *engine, string name = stream.str(); _window = 0; - GraphicsOutput *winout = - engine->make_output(pipe, name, 0, - FrameBufferProperties::get_default(), + GraphicsOutput *winout = + engine->make_output(pipe, name, 0, fbprops, props, flags, gsg, NULL); if (winout != (GraphicsOutput *)NULL) { _window = winout; diff --git a/panda/src/framework/windowFramework.h b/panda/src/framework/windowFramework.h index c224d6e2c6..71520167e9 100644 --- a/panda/src/framework/windowFramework.h +++ b/panda/src/framework/windowFramework.h @@ -63,7 +63,9 @@ public: protected: GraphicsOutput *open_window(const WindowProperties &props, int flags, GraphicsEngine *engine, GraphicsPipe *pipe, - GraphicsStateGuardian *gsg = NULL); + GraphicsStateGuardian *gsg = NULL, + const FrameBufferProperties &fbprops = + FrameBufferProperties::get_default()); void close_window(); public: From 904ed200b8fcd92f275bfa7a8a05661d5af1b8c8 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 27 Mar 2014 10:25:29 +0000 Subject: [PATCH 14/26] Add pyglet to hosted packages --- direct/src/p3d/thirdparty.pdef | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/direct/src/p3d/thirdparty.pdef b/direct/src/p3d/thirdparty.pdef index d272c805a0..6148f27d58 100644 --- a/direct/src/p3d/thirdparty.pdef +++ b/direct/src/p3d/thirdparty.pdef @@ -147,3 +147,9 @@ class box2d(package): require('panda3d') module('Box2D', required = True) + +class pyglet(package): + config(display_name = "pyglet") + require('panda3d') + + module('pyglet', required = True) From 44b4afe898cca3014db977ba6a2d3d0c4b3af9b6 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 27 Mar 2014 12:56:59 +0000 Subject: [PATCH 15/26] Fix issues building the plugin on Linux --- direct/src/plugin/handleStreamBuf.cxx | 1 + direct/src/plugin/mkdir_complete.cxx | 3 +-- direct/src/plugin/p3dAuthSession.cxx | 1 + direct/src/plugin/p3dHost.cxx | 4 ++++ makepanda/installpanda.py | 10 +++++----- makepanda/makepanda.py | 4 ++-- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/direct/src/plugin/handleStreamBuf.cxx b/direct/src/plugin/handleStreamBuf.cxx index 7b50e0074f..e1d1ba8a47 100644 --- a/direct/src/plugin/handleStreamBuf.cxx +++ b/direct/src/plugin/handleStreamBuf.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #endif // _WIN32 #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__) diff --git a/direct/src/plugin/mkdir_complete.cxx b/direct/src/plugin/mkdir_complete.cxx index c8b051a7fc..f2fb93e7b0 100755 --- a/direct/src/plugin/mkdir_complete.cxx +++ b/direct/src/plugin/mkdir_complete.cxx @@ -24,10 +24,9 @@ #include // for mkdir() #include #include // strerror() +#include #endif - - //////////////////////////////////////////////////////////////////// // Function: get_dirname // Description: Returns the directory component of the indicated diff --git a/direct/src/plugin/p3dAuthSession.cxx b/direct/src/plugin/p3dAuthSession.cxx index cc457260fb..6130119223 100644 --- a/direct/src/plugin/p3dAuthSession.cxx +++ b/direct/src/plugin/p3dAuthSession.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #endif //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dHost.cxx b/direct/src/plugin/p3dHost.cxx index 924d294f4b..68e74b7b98 100644 --- a/direct/src/plugin/p3dHost.cxx +++ b/direct/src/plugin/p3dHost.cxx @@ -22,6 +22,10 @@ #include +#ifndef _WIN32 +#include +#endif + //////////////////////////////////////////////////////////////////// // Function: P3DHost::Constructor // Access: Private diff --git a/makepanda/installpanda.py b/makepanda/installpanda.py index 2f3deadd5d..f398a95cfa 100644 --- a/makepanda/installpanda.py +++ b/makepanda/installpanda.py @@ -204,15 +204,15 @@ def InstallRuntime(destdir="", prefix="/usr", outputdir="built"): if sys.platform.startswith("freebsd"): oscmd("mkdir -m 0755 -p "+destdir+libdir+"/browser_plugins/symlinks/gecko19") oscmd("mkdir -m 0755 -p "+destdir+libdir+"/libxul/plugins") - oscmd("ln -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/browser_plugins/symlinks/gecko19/nppanda3d.so") - oscmd("ln -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/libxul/plugins/nppanda3d.so") + oscmd("ln -f -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/browser_plugins/symlinks/gecko19/nppanda3d.so") + oscmd("ln -f -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/libxul/plugins/nppanda3d.so") else: oscmd("mkdir -m 0755 -p "+destdir+libdir+"/mozilla/plugins") oscmd("mkdir -m 0755 -p "+destdir+libdir+"/mozilla-firefox/plugins") oscmd("mkdir -m 0755 -p "+destdir+libdir+"/xulrunner-addons/plugins") - oscmd("ln -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/mozilla/plugins/nppanda3d.so") - oscmd("ln -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/mozilla-firefox/plugins/nppanda3d.so") - oscmd("ln -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/xulrunner-addons/plugins/nppanda3d.so") + oscmd("ln -f -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/mozilla/plugins/nppanda3d.so") + oscmd("ln -f -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/mozilla-firefox/plugins/nppanda3d.so") + oscmd("ln -f -s "+libdir+"/nppanda3d.so "+destdir+libdir+"/xulrunner-addons/plugins/nppanda3d.so") WriteMimeFile(destdir+prefix+"/share/mime-info/panda3d-runtime.mime", MIME_INFO_PLUGIN) WriteKeysFile(destdir+prefix+"/share/mime-info/panda3d-runtime.keys", MIME_INFO_PLUGIN) WriteMimeXMLFile(destdir+prefix+"/share/mime/packages/panda3d-runtime.xml", MIME_INFO_PLUGIN) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 5f15299514..e5376e40ef 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -715,12 +715,12 @@ if (COMPILER=="GCC"): # We use a statically linked libboost_python on OSX rocket_libs += ("boost_python",) SmartPkgEnable("ROCKET", "", rocket_libs, "Rocket/Core.h") - SmartPkgEnable("GTK2", "gtk+-2.0") SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h") SmartPkgEnable("OPENSSL", "openssl", ("ssl", "crypto"), ("openssl/ssl.h", "openssl/crypto.h")) SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config") SmartPkgEnable("ZLIB", "zlib", ("z"), "zlib.h") + SmartPkgEnable("GTK2", "gtk+-2.0") if (RTDIST and GetHost() == "darwin" and "PYTHONVERSION" in SDK): # Don't use the framework for the OSX rtdist build. I'm afraid it gives problems somewhere. @@ -4721,7 +4721,7 @@ if (RTDIST or RUNTIME): # if (RUNTIME and PkgSkip("NPAPI")==0): - OPTS=['DIR:direct/src/plugin_npapi', 'RUNTIME'] + OPTS=['DIR:direct/src/plugin_npapi', 'RUNTIME', 'GTK2'] if GetTarget() == 'windows': nppanda3d_rc = {"name" : "Panda3D Game Engine Plug-in", "version" : VERSION, From d5d5de1d7e23bd8b28c40d6e517514e96b1d61a2 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 27 Mar 2014 15:15:58 +0000 Subject: [PATCH 16/26] Make iterators work with interrogate by mapping None to NULL for the iternext method. Not the best solution, but is easy and fits most use cases. --- .../interfaceMakerPythonNative.cxx | 27 +++++++++++++++++-- .../interrogate/interfaceMakerPythonNative.h | 1 + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 2e089b09d8..ca6c6d5ca7 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -507,9 +507,9 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { return true; } - if (method_name == "next") { + if (method_name == "next" || method_name == "__next__") { def._answer_location = "tp_iternext"; - def._wrapper_type = WT_no_params; + def._wrapper_type = WT_iter_next; return true; } } @@ -1700,6 +1700,29 @@ write_module_class(ostream &out, Object *obj) { } break; + case WT_iter_next: + // PyObject *func(PyObject *self) + // However, returns NULL instead of None + { + Function *func = rfi->first; + out << "//////////////////\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "//////////////////\n"; + out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self) {\n"; + out << " PyObject *args = Py_BuildValue(\"()\");\n"; + out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; + out << " Py_DECREF(args);\n"; + out << " if (result == Py_None) {\n"; + out << " Py_DECREF(Py_None);\n"; + out << " return NULL;\n"; + out << " } else {\n"; + out << " return result;\n"; + out << " }\n"; + out << "}\n\n"; + } + break; + case WT_none: break; } diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 32ddd65af7..3bcb9d3b04 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -76,6 +76,7 @@ private: WT_inquiry, WT_getbuffer, WT_releasebuffer, + WT_iter_next, }; class SlottedFunctionDef { From fd76cff5f0781a7c61bf379d3b433f00be6b9d6a Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 29 Mar 2014 09:32:52 +0000 Subject: [PATCH 17/26] Patch by phx to support -C in all cases --- panda/src/downloadertools/multify.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/panda/src/downloadertools/multify.cxx b/panda/src/downloadertools/multify.cxx index 54482e4964..d9736336c5 100644 --- a/panda/src/downloadertools/multify.cxx +++ b/panda/src/downloadertools/multify.cxx @@ -202,8 +202,8 @@ help() { " -C \n" - " With -x, change to the named directory before extracting files;\n" - " that is, extract subfiles into the named directory.\n\n" + " Change to the named directory before working on files;\n" + " that is, extraction/creation/update and replace will be based on this path\n\n" " -O\n" " With -x, extract subfiles to standard output instead of to disk.\n\n" @@ -419,6 +419,12 @@ add_files(const vector_string ¶ms) { filenames.push_back(subfile_name); } + // Change current working directory, if requested. + if (got_chdir_to && chdir(chdir_to.c_str()) != 0) { + cout << "Failed to chdir to " << chdir_to << ": " << strerror(errno) << endl; + return false; + } + bool okflag = do_add_files(multifile, filenames); bool needs_repack = multifile->needs_repack(); From 95edd07b25d5313f2dd2a80f0feff7e5a8639957 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 29 Mar 2014 13:50:55 +0000 Subject: [PATCH 18/26] Fix use of chdir --- panda/src/downloadertools/multify.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/downloadertools/multify.cxx b/panda/src/downloadertools/multify.cxx index d9736336c5..460c34b9a5 100644 --- a/panda/src/downloadertools/multify.cxx +++ b/panda/src/downloadertools/multify.cxx @@ -420,7 +420,7 @@ add_files(const vector_string ¶ms) { } // Change current working directory, if requested. - if (got_chdir_to && chdir(chdir_to.c_str()) != 0) { + if (got_chdir_to && !chdir_to.chdir()) { cout << "Failed to chdir to " << chdir_to << ": " << strerror(errno) << endl; return false; } From d792c930267157b3a970c59b92fd657cfad31b57 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 4 Apr 2014 08:45:49 +0000 Subject: [PATCH 19/26] Overhaul stereo FBOs in Panda making it more reliable, fix MRT bugs, disable auto-GLSL profile choosing on AMD, add max_color_targets (not yet implemented) --- panda/src/display/config_display.cxx | 11 ++ panda/src/display/config_display.h | 1 + panda/src/display/displayRegion.I | 29 +---- panda/src/display/displayRegion.cxx | 11 +- panda/src/display/displayRegion.h | 5 +- panda/src/display/graphicsOutput.I | 3 +- panda/src/display/graphicsOutput.cxx | 98 +++++++++++------ panda/src/display/graphicsOutput.h | 2 +- panda/src/display/graphicsStateGuardian.I | 29 ++++- panda/src/display/graphicsStateGuardian.cxx | 13 ++- panda/src/display/graphicsStateGuardian.h | 7 +- panda/src/display/stereoDisplayRegion.cxx | 24 ++-- panda/src/display/stereoDisplayRegion.h | 2 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 26 +++-- panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 12 +- panda/src/dxgsg8/dxTextureContext8.cxx | 6 +- panda/src/dxgsg8/dxTextureContext8.h | 2 +- panda/src/dxgsg8/wdxGraphicsBuffer8.cxx | 2 +- panda/src/dxgsg8/wdxGraphicsBuffer8.h | 4 +- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 23 ++-- panda/src/dxgsg9/dxGraphicsStateGuardian9.h | 12 +- panda/src/dxgsg9/dxTextureContext9.cxx | 6 +- panda/src/dxgsg9/dxTextureContext9.h | 2 +- panda/src/dxgsg9/wdxGraphicsBuffer9.cxx | 2 +- panda/src/dxgsg9/wdxGraphicsBuffer9.h | 4 +- panda/src/glstuff/glGraphicsBuffer_src.cxx | 104 ++++++++++-------- panda/src/glstuff/glGraphicsBuffer_src.h | 5 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 104 ++++++++++-------- .../src/glstuff/glGraphicsStateGuardian_src.h | 5 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 6 +- .../tinydisplay/tinyGraphicsStateGuardian.cxx | 17 +-- .../tinydisplay/tinyGraphicsStateGuardian.h | 4 +- panda/src/wgldisplay/wglGraphicsBuffer.cxx | 2 +- panda/src/wgldisplay/wglGraphicsBuffer.h | 2 +- 34 files changed, 327 insertions(+), 258 deletions(-) diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index 68986ca5ed..e89a7df768 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -172,6 +172,17 @@ ConfigVariableInt max_texture_stages "this number of texture stages simultaneously, regardless of " "what the GSG says it can do.")); +ConfigVariableInt max_color_targets +("max-color-targets", -1, + PRC_DESC("Set this to a positive integer to limit the number of " + "color targets reported by the GSG. This can be used to limit " + "the amount of render targets Panda will attempt to use. " + "If this is zero or less, the GSG will report its honest number " + "of color targets, allowing Panda the full use of the graphics " + "card; if it is 1 or more, then Panda will never allow more than " + "this number of color targets simultaneously, regardless of " + "what the GSG says it can do.")); + ConfigVariableBool support_render_texture ("support-render-texture", true, PRC_DESC("Set this true allow use of the render-to-a-texture feature, if it " diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index fa3c372cda..2cd7569f02 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -52,6 +52,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool force_parasite_buffer; extern EXPCL_PANDA_DISPLAY ConfigVariableBool prefer_single_buffer; extern EXPCL_PANDA_DISPLAY ConfigVariableInt max_texture_stages; +extern EXPCL_PANDA_DISPLAY ConfigVariableInt max_color_targets; extern EXPCL_PANDA_DISPLAY ConfigVariableBool support_render_texture; extern EXPCL_PANDA_DISPLAY ConfigVariableBool support_rescale_normal; extern EXPCL_PANDA_DISPLAY ConfigVariableBool support_stencil; diff --git a/panda/src/display/displayRegion.I b/panda/src/display/displayRegion.I index e71bbd4271..bb549873c0 100644 --- a/panda/src/display/displayRegion.I +++ b/panda/src/display/displayRegion.I @@ -245,7 +245,7 @@ get_texture_reload_priority() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: set_cube_map_index(int cube_map_index) { - set_target_tex_page(cube_map_index, 0); + set_target_tex_page(cube_map_index); } //////////////////////////////////////////////////////////////////// @@ -262,20 +262,6 @@ get_target_tex_page() const { return cdata->_target_tex_page; } -//////////////////////////////////////////////////////////////////// -// Function: DisplayRegion::get_target_tex_view -// Access: Published -// Description: Returns the target view number associated with this -// particular DisplayRegion, or -1 if it is not -// associated with a view. See -// set_target_tex_page(). -//////////////////////////////////////////////////////////////////// -INLINE int DisplayRegion:: -get_target_tex_view() const { - CDReader cdata(_cycler); - return cdata->_target_tex_view; -} - //////////////////////////////////////////////////////////////////// // Function: DisplayRegion::set_cull_callback // Access: Published @@ -812,19 +798,6 @@ get_target_tex_page() const { return _cdata->_target_tex_page; } -//////////////////////////////////////////////////////////////////// -// Function: DisplayRegionPipelineReader::get_target_tex_view -// Access: Published -// Description: Returns the target view number associated with this -// particular DisplayRegion, or -1 if it is not -// associated with a view. See -// set_target_tex_page(). -//////////////////////////////////////////////////////////////////// -INLINE int DisplayRegionPipelineReader:: -get_target_tex_view() const { - return _cdata->_target_tex_view; -} - //////////////////////////////////////////////////////////////////// // Function: DisplayRegionPipelineReader::get_draw_callback // Access: Published diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index dfdf3b9f8e..5bf57bf2fa 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -404,12 +404,11 @@ get_cull_traverser() { // and/or stereo textures. //////////////////////////////////////////////////////////////////// void DisplayRegion:: -set_target_tex_page(int page, int view) { +set_target_tex_page(int page) { int pipeline_stage = Thread::get_current_pipeline_stage(); nassertv(pipeline_stage == 0); CDWriter cdata(_cycler); cdata->_target_tex_page = page; - cdata->_target_tex_view = view; } //////////////////////////////////////////////////////////////////// @@ -587,7 +586,7 @@ get_screenshot() { RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type(), _window->get_fb_properties()); - if (!gsg->framebuffer_copy_to_ram(tex, -1, this, buffer)) { + if (!gsg->framebuffer_copy_to_ram(tex, 0, -1, this, buffer)) { return NULL; } @@ -823,8 +822,7 @@ CData() : _sort(0), _stereo_channel(Lens::SC_mono), _tex_view_offset(0), - _target_tex_page(-1), - _target_tex_view(-1) + _target_tex_page(-1) { } @@ -849,8 +847,7 @@ CData(const DisplayRegion::CData ©) : _sort(copy._sort), _stereo_channel(copy._stereo_channel), _tex_view_offset(copy._tex_view_offset), - _target_tex_page(copy._target_tex_page), - _target_tex_view(copy._target_tex_view) + _target_tex_page(copy._target_tex_page) { } diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index 8ab64d7eca..0de061ab1d 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -112,9 +112,8 @@ PUBLISHED: CullTraverser *get_cull_traverser(); INLINE void set_cube_map_index(int cube_map_index); - virtual void set_target_tex_page(int page, int view); + virtual void set_target_tex_page(int page); INLINE int get_target_tex_page() const; - INLINE int get_target_tex_view() const; INLINE void set_cull_callback(CallbackObject *object); INLINE void clear_cull_callback(); @@ -213,7 +212,6 @@ private: Lens::StereoChannel _stereo_channel; int _tex_view_offset; int _target_tex_page; - int _target_tex_view; PT(CallbackObject) _cull_callback; PT(CallbackObject) _draw_callback; @@ -312,7 +310,6 @@ public: INLINE int get_tex_view_offset(); INLINE bool get_clear_depth_between_eyes() const; INLINE int get_target_tex_page() const; - INLINE int get_target_tex_view() const; INLINE CallbackObject *get_draw_callback() const; INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const; diff --git a/panda/src/display/graphicsOutput.I b/panda/src/display/graphicsOutput.I index 7e4e80d8ad..c5afb051c7 100644 --- a/panda/src/display/graphicsOutput.I +++ b/panda/src/display/graphicsOutput.I @@ -863,12 +863,11 @@ end_frame_spam(FrameMode mode) { // Function: GraphicsOutput::clear_cube_map_selection // Access: Public // Description: Clear the variables that select a cube-map face (or -// other multipage or multiview texture face). +// other multipage texture face). //////////////////////////////////////////////////////////////////// INLINE void GraphicsOutput:: clear_cube_map_selection() { _target_tex_page = -1; - _target_tex_view = -1; _prev_page_dr = NULL; } diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 05863d4751..273c9d9ae7 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -107,7 +107,6 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe, _is_valid = false; _flip_ready = false; _target_tex_page = -1; - _target_tex_view = -1; _prev_page_dr = NULL; _sort = 0; _child_sort = 0; @@ -373,6 +372,12 @@ add_render_texture(Texture *tex, RenderTextureMode mode, // which has system-imposed restrictions on size). tex->set_size_padded(get_x_size(), get_y_size(), tex->get_z_size()); + if (_fb_properties.is_stereo() && plane == RTP_color) { + if (tex->get_num_views() < 2) { + tex->set_num_views(2); + } + } + if (!support_render_texture || !get_supports_render_texture()) { // Binding is not supported or it is disabled, so just fall back // to copy instead. @@ -1069,7 +1074,7 @@ make_cube_map(const string &name, int size, NodePath &camera_rig, DisplayRegion *dr; dr = buffer->make_display_region(); - dr->set_target_tex_page(i, 0); + dr->set_target_tex_page(i); dr->copy_clear_settings(*this); dr->set_camera(camera_np); } @@ -1342,38 +1347,34 @@ end_frame(FrameMode mode, Thread *current_thread) { void GraphicsOutput:: change_scenes(DisplayRegionPipelineReader *new_dr) { int new_target_tex_page = new_dr->get_target_tex_page(); - int new_target_tex_view = new_dr->get_target_tex_view(); - if ((new_target_tex_page != -1 && new_target_tex_page != _target_tex_page) || - new_target_tex_view != _target_tex_view) { + + if (new_target_tex_page != -1 && new_target_tex_page != _target_tex_page) { + + if (new_target_tex_page == -1) { + new_target_tex_page = 0; + } int old_target_tex_page = _target_tex_page; - int old_target_tex_view = _target_tex_view; DisplayRegion *old_page_dr = _prev_page_dr; _target_tex_page = new_target_tex_page; - _target_tex_view = new_target_tex_view; _prev_page_dr = new_dr->get_object(); CDReader cdata(_cycler); RenderTextures::const_iterator ri; for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) { RenderTextureMode rtm_mode = (*ri)._rtm_mode; + RenderTexturePlane plane = (*ri)._plane; Texture *texture = (*ri)._texture; if (rtm_mode != RTM_none) { if (rtm_mode == RTM_bind_or_copy || rtm_mode == RTM_bind_layered) { // In render-to-texture mode, switch the rendering backend // to the new page, so that the subsequent frame will be // rendered to the correct page. - select_target_tex_page(_target_tex_page, _target_tex_view); + select_target_tex_page(_target_tex_page); } else if (old_target_tex_page != -1) { // In copy-to-texture mode, copy the just-rendered framebuffer // to the old texture page. - // TODO: we should probably pass the view parameter into - // framebuffer_copy_to_xxx(), as we do the page parameter. - // Instead these methods draw the view parameter from - // dr->get_target_tex_view(), which is not altogether wrong - // but is a strange approach. - nassertv(old_page_dr != (DisplayRegion *)NULL); if (display_cat.is_debug()) { display_cat.debug() @@ -1383,12 +1384,31 @@ change_scenes(DisplayRegionPipelineReader *new_dr) { } RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type(), get_fb_properties()); - if (rtm_mode == RTM_copy_ram) { - _gsg->framebuffer_copy_to_ram(texture, old_target_tex_page, - old_page_dr, buffer); + + if (plane == RTP_color && _fb_properties.is_stereo()) { + // We've got two texture views to copy. + RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right); + RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left); + + if (rtm_mode == RTM_copy_ram) { + _gsg->framebuffer_copy_to_ram(texture, 0, old_target_tex_page, + old_page_dr, left); + _gsg->framebuffer_copy_to_ram(texture, 1, old_target_tex_page, + old_page_dr, right); + } else { + _gsg->framebuffer_copy_to_texture(texture, 0, old_target_tex_page, + old_page_dr, left); + _gsg->framebuffer_copy_to_texture(texture, 1, old_target_tex_page, + old_page_dr, right); + } } else { - _gsg->framebuffer_copy_to_texture(texture, old_target_tex_page, - old_page_dr, buffer); + if (rtm_mode == RTM_copy_ram) { + _gsg->framebuffer_copy_to_ram(texture, 0, old_target_tex_page, + old_page_dr, buffer); + } else { + _gsg->framebuffer_copy_to_texture(texture, 0, old_target_tex_page, + old_page_dr, buffer); + } } } } @@ -1402,12 +1422,11 @@ change_scenes(DisplayRegionPipelineReader *new_dr) { // Description: Called internally when the window is in // render-to-a-texture mode and we are in the process of // rendering the six faces of a cube map, or any other -// multi-page and/or multi-view texture. This should do -// whatever needs to be done to switch the buffer to the -// indicated page and view. +// multi-page texture. This should do whatever needs +// to be done to switch the buffer to the indicated page. //////////////////////////////////////////////////////////////////// void GraphicsOutput:: -select_target_tex_page(int, int) { +select_target_tex_page(int) { } //////////////////////////////////////////////////////////////////// @@ -1588,25 +1607,34 @@ copy_to_textures() { } bool copied = false; + DisplayRegion *dr = _overlay_display_region; if (_prev_page_dr != (DisplayRegion *)NULL) { + dr = _prev_page_dr; + } + + if (plane == RTP_color && _fb_properties.is_stereo()) { + // We've got two texture views to copy. + RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right); + RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left); + if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) { - copied = - _gsg->framebuffer_copy_to_ram(texture, _target_tex_page, - _prev_page_dr, buffer); + copied = _gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page, + dr, left); + copied = _gsg->framebuffer_copy_to_ram(texture, 1, _target_tex_page, + dr, right) && copied; } else { - copied = - _gsg->framebuffer_copy_to_texture(texture, _target_tex_page, - _prev_page_dr, buffer); + copied = _gsg->framebuffer_copy_to_texture(texture, 0, _target_tex_page, + dr, left); + copied = _gsg->framebuffer_copy_to_texture(texture, 1, _target_tex_page, + dr, right) && copied; } } else { if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) { - copied = - _gsg->framebuffer_copy_to_ram(texture, _target_tex_page, - _overlay_display_region, buffer); + copied = _gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page, + dr, buffer); } else { - copied = - _gsg->framebuffer_copy_to_texture(texture, _target_tex_page, - _overlay_display_region, buffer); + copied = _gsg->framebuffer_copy_to_texture(texture, 0, _target_tex_page, + dr, buffer); } } if (!copied) { diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 1e40a7051b..f138a64433 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -260,7 +260,7 @@ public: virtual void end_frame(FrameMode mode, Thread *current_thread); void change_scenes(DisplayRegionPipelineReader *new_dr); - virtual void select_target_tex_page(int page, int view); + virtual void select_target_tex_page(int page); // These methods will be called within the app (main) thread. virtual void begin_flip(); diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index ce54db6881..4bcc120f72 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -702,15 +702,38 @@ get_supports_geometry_instancing() const { return _supports_geometry_instancing; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_max_color_targets +// Access: Published +// Description: Returns the maximum number of simultaneous color +// textures that may be attached for render-to-texture, +// as supported by this particular GSG. If you exceed +// this number, the lowest-priority render targets will +// not be applied. Use RenderTarget::set_priority() to +// adjust the relative importance of the different +// render targets. +// +// The value returned may not be meaningful until after +// the graphics context has been fully created (e.g. the +// window has been opened). +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsStateGuardian:: +get_max_color_targets() const { + if (max_color_targets > 0) { + return min(_max_color_targets, (int)max_color_targets); + } + return _max_color_targets; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_maximum_simultaneous_render_targets // Access: Published -// Description: Returns the maximum simultaneous render targets -// supported. +// Description: Deprecated. Use get_max_color_targets() instead, +// which returns the exact same value. //////////////////////////////////////////////////////////////////// INLINE int GraphicsStateGuardian:: get_maximum_simultaneous_render_targets() const { - return _maximum_simultaneous_render_targets; + return get_max_color_targets(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 4aea74171a..715d1a7fee 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -218,7 +218,8 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _supports_two_sided_stencil = false; _supports_geometry_instancing = false; - _maximum_simultaneous_render_targets = 1; + // Assume a maximum of 1 render target in absence of MRT. + _max_color_targets = 1; _supported_geom_rendering = 0; @@ -1317,14 +1318,14 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { case Lens::SC_left: _color_write_mask = dr->get_window()->get_left_eye_color_mask(); if (_current_properties->is_stereo()) { - _stereo_buffer_mask = ~(RenderBuffer::T_front_right | RenderBuffer::T_back_right); + _stereo_buffer_mask = ~RenderBuffer::T_right; } break; case Lens::SC_right: _color_write_mask = dr->get_window()->get_right_eye_color_mask(); if (_current_properties->is_stereo()) { - _stereo_buffer_mask = ~(RenderBuffer::T_front_left | RenderBuffer::T_back_left); + _stereo_buffer_mask = ~RenderBuffer::T_left; } break; @@ -2150,7 +2151,7 @@ do_issue_light() { // copy. //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: -framebuffer_copy_to_texture(Texture *, int, const DisplayRegion *, +framebuffer_copy_to_texture(Texture *, int, int, const DisplayRegion *, const RenderBuffer &) { return false; } @@ -2167,7 +2168,7 @@ framebuffer_copy_to_texture(Texture *, int, const DisplayRegion *, // indicated texture. //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: -framebuffer_copy_to_ram(Texture *, int, const DisplayRegion *, +framebuffer_copy_to_ram(Texture *, int, int, const DisplayRegion *, const RenderBuffer &) { return false; } @@ -2722,7 +2723,7 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) { for (int i = 0; i < 6; ++i) { PT(DisplayRegion) dr = sbuffer->make_mono_display_region(0, 1, 0, 1); dr->set_lens_index(i); - dr->set_target_tex_page(i, 0); + dr->set_target_tex_page(i); dr->set_camera(light_np); dr->set_clear_depth_active(true); } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index d5a5f08eec..3f7efa8297 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -150,6 +150,7 @@ PUBLISHED: INLINE bool get_supports_two_sided_stencil() const; INLINE bool get_supports_geometry_instancing() const; + INLINE int get_max_color_targets() const; INLINE int get_maximum_simultaneous_render_targets() const; INLINE int get_shader_model() const; @@ -308,9 +309,9 @@ public: virtual void do_issue_light(); virtual bool framebuffer_copy_to_texture - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb); + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb); virtual bool framebuffer_copy_to_ram - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb); + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb); virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id); @@ -495,7 +496,7 @@ protected: bool _supports_two_sided_stencil; bool _supports_geometry_instancing; - int _maximum_simultaneous_render_targets; + int _max_color_targets; int _supported_geom_rendering; bool _color_scale_via_lighting; diff --git a/panda/src/display/stereoDisplayRegion.cxx b/panda/src/display/stereoDisplayRegion.cxx index c328bc3a33..828ef7756a 100644 --- a/panda/src/display/stereoDisplayRegion.cxx +++ b/panda/src/display/stereoDisplayRegion.cxx @@ -52,9 +52,17 @@ StereoDisplayRegion:: //////////////////////////////////////////////////////////////////// void StereoDisplayRegion:: set_clear_active(int n, bool clear_active) { - //DisplayRegion::set_clear_active(n, clear_active); - _left_eye->set_clear_active(n, clear_active); - _right_eye->set_clear_active(n, clear_active); + // The clear_active flag gets set only on the parent, stereo display + // region. + DisplayRegion::set_clear_active(n, clear_active); + + // Except for non-color buffers. These also get set on the + // right display region by default, on the assumption that we want + // to clear these buffers between drawing the eyes, and that the + // right eye is the second of the pair. + if (n != RTP_color) { + _right_eye->set_clear_active(n, clear_active); + } } //////////////////////////////////////////////////////////////////// @@ -64,7 +72,7 @@ set_clear_active(int n, bool clear_active) { //////////////////////////////////////////////////////////////////// void StereoDisplayRegion:: set_clear_value(int n, const LColor &clear_value) { - //DisplayRegion::set_clear_value(n, clear_value); + DisplayRegion::set_clear_value(n, clear_value); _left_eye->set_clear_value(n, clear_value); _right_eye->set_clear_value(n, clear_value); } @@ -290,10 +298,10 @@ set_cull_traverser(CullTraverser *trav) { // right DisplayRegions to the indicated value. //////////////////////////////////////////////////////////////////// void StereoDisplayRegion:: -set_target_tex_page(int page, int view) { - DisplayRegion::set_target_tex_page(page, view); - _left_eye->set_target_tex_page(page, view); - _right_eye->set_target_tex_page(page, view); +set_target_tex_page(int page) { + DisplayRegion::set_target_tex_page(page); + _left_eye->set_target_tex_page(page); + _right_eye->set_target_tex_page(page); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/stereoDisplayRegion.h b/panda/src/display/stereoDisplayRegion.h index 01b6c3905c..56882d4606 100644 --- a/panda/src/display/stereoDisplayRegion.h +++ b/panda/src/display/stereoDisplayRegion.h @@ -61,7 +61,7 @@ PUBLISHED: virtual void set_incomplete_render(bool incomplete_render); virtual void set_texture_reload_priority(int texture_reload_priority); virtual void set_cull_traverser(CullTraverser *trav); - virtual void set_target_tex_page(int page, int view); + virtual void set_target_tex_page(int page); virtual void output(ostream &out) const; virtual PT(PandaNode) make_cull_result_graph(); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index b344e9964d..c8b0730ea4 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -1493,8 +1493,8 @@ end_draw_primitives() { // copy. //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian8:: -framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb) { +framebuffer_copy_to_texture(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { set_read_buffer(rb); int orig_x = tex->get_x_size(); @@ -1504,8 +1504,8 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, int xo, yo, w, h; dr->get_region_pixels_i(xo, yo, w, h); tex->set_size_padded(w, h); - - TextureContext *tc = tex->prepare_now(0, get_prepared_objects(), this); + + TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { return false; } @@ -1520,7 +1520,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, if (tex->get_texture_type() != Texture::TT_2d_texture) { // For a specialty texture like a cube map, go the slow route // through RAM for now. - return do_framebuffer_copy_to_ram(tex, z, dr, rb, true); + return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, true); } nassertr(dtc->get_d3d_2d_texture() != NULL, false); @@ -1592,7 +1592,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, if (FAILED(hr)) { dxgsg8_cat.info() << "CopyRects failed in copy_texture " << D3DERRORSTRING(hr); - okflag = framebuffer_copy_to_ram(tex, z, dr, rb); + okflag = framebuffer_copy_to_ram(tex, view, z, dr, rb); } SAFE_RELEASE(render_target); @@ -1605,7 +1605,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, } else { // The copy failed. Fall back to copying it to RAM and back. // Terribly slow, but what are you going to do? - return do_framebuffer_copy_to_ram(tex, z, dr, rb, true); + return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, true); } return true; @@ -1623,8 +1623,9 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, // indicated texture. //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian8:: -framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb) { - return do_framebuffer_copy_to_ram(tex, z, dr, rb, false); +framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { + return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, false); } //////////////////////////////////////////////////////////////////// @@ -1637,8 +1638,9 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend // copies to texture memory). //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian8:: -do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb, bool inverted) { +do_framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb, + bool inverted) { set_read_buffer(rb); RECT rect; @@ -1779,7 +1781,7 @@ do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, copy_inverted = !copy_inverted; } DXTextureContext8::d3d_surface_to_texture(rect, temp_surface, - copy_inverted, tex, z); + copy_inverted, tex, view, z); RELEASE(temp_surface, dxgsg8, "temp_surface", RELEASE_ONCE); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 4116089220..9a4412e01b 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -98,12 +98,16 @@ public: bool force); virtual void end_draw_primitives(); - virtual bool framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, + virtual bool framebuffer_copy_to_texture(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb); - virtual bool framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, + virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb); - bool do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb, bool inverted); + bool do_framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, + const RenderBuffer &rb, + bool inverted); virtual void reset(); diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index a14783db23..ab651d6d0c 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -1062,7 +1062,8 @@ extract_texture_data() { //////////////////////////////////////////////////////////////////// HRESULT DXTextureContext8:: d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, - bool inverted, Texture *result, int z) { + bool inverted, Texture *result, int view, int z) { + // still need custom conversion since d3d/d3dx has no way to convert // arbitrary fmt to ARGB in-memory user buffer @@ -1079,6 +1080,9 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, nassertr(z < result->get_z_size(), E_FAIL); buf += z * result->get_expected_ram_page_size(); } + if (view > 0) { + buf += (view * result->get_z_size()) * result->get_expected_ram_page_size(); + } if (IsBadWritePtr(d3d_surface, sizeof(DWORD))) { dxgsg8_cat.error() diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h index 39c6e0c7c4..5fc06f8d0a 100644 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ b/panda/src/dxgsg8/dxTextureContext8.h @@ -44,7 +44,7 @@ public: static HRESULT d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface8 *d3d_surface, bool inverted, Texture *result, - int z); + int view, int z); private: HRESULT fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format); diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx index fea31ccfcc..8d5c8bb77e 100644 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx @@ -403,7 +403,7 @@ rebuild_bitplanes() { // the indicated face. //////////////////////////////////////////////////////////////////// void wdxGraphicsBuffer8:: -select_target_tex_page(int page, int view) { +select_target_tex_page(int page) { _cube_map_index = page; HRESULT hr; diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.h b/panda/src/dxgsg8/wdxGraphicsBuffer8.h index cb5d21ed9c..fe3c5a95de 100644 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.h +++ b/panda/src/dxgsg8/wdxGraphicsBuffer8.h @@ -45,8 +45,8 @@ public: virtual bool begin_frame(FrameMode mode, Thread *current_thread); virtual void end_frame(FrameMode mode, Thread *current_thread); - - virtual void select_target_tex_page(int page, int view); + + virtual void select_target_tex_page(int page); virtual void process_events(); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 1eaef91715..fd48033eec 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -1887,8 +1887,8 @@ end_draw_primitives() { // copy. //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian9:: -framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb) { +framebuffer_copy_to_texture(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { set_read_buffer(rb); int orig_x = tex->get_x_size(); @@ -1918,7 +1918,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, if (tex->get_texture_type() != Texture::TT_2d_texture) { // For a specialty texture like a cube map, go the slow route // through RAM for now. - return do_framebuffer_copy_to_ram(tex, z, dr, rb, true); + return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, true); } nassertr(dtc->get_d3d_2d_texture() != NULL, false); @@ -2020,7 +2020,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, } else { // The copy failed. Fall back to copying it to RAM and back. // Terribly slow, but what are you going to do? - return do_framebuffer_copy_to_ram(tex, z, dr, rb, true); + return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, true); } return true; @@ -2038,9 +2038,9 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, // indicated texture. //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian9:: -framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb) { - return do_framebuffer_copy_to_ram(tex, z, dr, rb, false); +framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { + return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, false); } //////////////////////////////////////////////////////////////////// @@ -2053,8 +2053,9 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, // copies to texture memory). //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian9:: -do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb, bool inverted) { +do_framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb, + bool inverted) { set_read_buffer(rb); RECT rect; @@ -2212,7 +2213,7 @@ do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, copy_inverted = !copy_inverted; } DXTextureContext9::d3d_surface_to_texture(rect, temp_surface, - copy_inverted, tex, z); + copy_inverted, tex, view, z); RELEASE(temp_surface, dxgsg9, "temp_surface", RELEASE_ONCE); @@ -2445,7 +2446,7 @@ reset() { _supports_stencil_wrap = (d3d_caps.StencilCaps & D3DSTENCILCAPS_INCR) && (d3d_caps.StencilCaps & D3DSTENCILCAPS_DECR); _supports_two_sided_stencil = ((d3d_caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0); - _maximum_simultaneous_render_targets = d3d_caps.NumSimultaneousRTs; + _max_color_targets = d3d_caps.NumSimultaneousRTs; _supports_depth_bias = ((d3d_caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) == (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index c9c0df9fd9..c3d3c72bf7 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -126,12 +126,16 @@ public: bool force); virtual void end_draw_primitives(); - virtual bool framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, + virtual bool framebuffer_copy_to_texture(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb); - virtual bool framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, + virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb); - bool do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb, bool inverted); + bool do_framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, + const RenderBuffer &rb, + bool inverted); void reset_render_states (void); virtual void reset(); diff --git a/panda/src/dxgsg9/dxTextureContext9.cxx b/panda/src/dxgsg9/dxTextureContext9.cxx index a178fd7484..9fd73be358 100755 --- a/panda/src/dxgsg9/dxTextureContext9.cxx +++ b/panda/src/dxgsg9/dxTextureContext9.cxx @@ -1303,7 +1303,8 @@ extract_texture_data(DXScreenData &screen) { //////////////////////////////////////////////////////////////////// HRESULT DXTextureContext9:: d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, - bool inverted, Texture *result, int z) { + bool inverted, Texture *result, int view, int z) { + // still need custom conversion since d3d/d3dx has no way to convert // arbitrary fmt to ARGB in-memory user buffer @@ -1320,6 +1321,9 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, nassertr(z < result->get_z_size(), E_FAIL); buf += z * result->get_expected_ram_page_size(); } + if (view > 0) { + buf += (view * result->get_z_size()) * result->get_expected_ram_page_size(); + } if (IsBadWritePtr(d3d_surface, sizeof(DWORD))) { dxgsg9_cat.error() diff --git a/panda/src/dxgsg9/dxTextureContext9.h b/panda/src/dxgsg9/dxTextureContext9.h index 3d8549b3e4..01a5838042 100755 --- a/panda/src/dxgsg9/dxTextureContext9.h +++ b/panda/src/dxgsg9/dxTextureContext9.h @@ -46,7 +46,7 @@ public: static HRESULT d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface, bool inverted, Texture *result, - int z); + int view, int z); private: HRESULT fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format); diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx index 8fceeb9469..646a016185 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx @@ -591,7 +591,7 @@ rebuild_bitplanes() { // the indicated face. //////////////////////////////////////////////////////////////////// void wdxGraphicsBuffer9:: -select_target_tex_page(int page, int view) { +select_target_tex_page(int page) { DWORD render_target_index; diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.h b/panda/src/dxgsg9/wdxGraphicsBuffer9.h index 91dfd0539f..d876c2505e 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.h +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.h @@ -46,8 +46,8 @@ public: virtual bool begin_frame(FrameMode mode, Thread *current_thread); virtual void end_frame(FrameMode mode, Thread *current_thread); - virtual void select_target_tex_page(int page, int view); - + virtual void select_target_tex_page(int page); + virtual void process_events(); virtual bool share_depth_buffer(GraphicsOutput *graphics_output); diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 82590c816b..0e094f4eef 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -81,7 +81,6 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe, _shared_depth_buffer = 0; _bound_tex_page = -1; - _bound_tex_view = 0; } //////////////////////////////////////////////////////////////////// @@ -431,6 +430,17 @@ rebuild_bitplanes() { int next = GL_COLOR_ATTACHMENT0_EXT; if (attach[RTP_color] || _fb_properties.get_color_bits() > 0) { bind_slot(layer, rb_resize, attach, RTP_color, next++); + + if (_fb_properties.is_stereo()) { + // The texture has already been initialized, so bind it straight away. + if (attach[RTP_color] != NULL) { + attach_tex(layer, 1, attach[RTP_color], next++); + } else { + //XXX hack: I needed a slot to use, and we don't currently use RTP_stencil + // which is treated as a color attachment below, so this fits the bill. + bind_slot(layer, rb_resize, attach, RTP_stencil, next++); + } + } _have_any_color = true; } @@ -471,6 +481,9 @@ rebuild_bitplanes() { int next = GL_COLOR_ATTACHMENT0_EXT; if (attach[RTP_color] || _fb_properties.get_color_bits() > 0) { bind_slot_multisample(rb_resize, attach, RTP_color, next++); + if (_fb_properties.is_stereo()) { + //TODO: figure out how multisample is supposed to work with stereo buffers. + } } for (int i=0; i<_fb_properties.get_aux_rgba(); i++) { @@ -498,7 +511,6 @@ rebuild_bitplanes() { _fb_properties.set_alpha_bits(0); } - _bound_tex_view = 0; _initial_clear = false; report_my_gl_errors(); @@ -763,6 +775,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, // Allocate and bind the renderbuffer. glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rb[slot]); + if (slot == RTP_depth_stencil) { GLCAT.debug() << "Creating depth stencil renderbuffer.\n"; // Allocate renderbuffer storage for depth stencil. @@ -811,13 +824,16 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, } else { GLCAT.debug() << "Creating color renderbuffer.\n"; glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y); - GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0; - glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT, &red_size); - glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT, &green_size); - glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT, &blue_size); - glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT, &alpha_size); - _fb_properties.set_color_bits(red_size + green_size + blue_size); - _fb_properties.set_alpha_bits(alpha_size); + + if (attachpoint == GL_COLOR_ATTACHMENT0_EXT) { + GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0; + glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_RED_SIZE_EXT, &red_size); + glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_GREEN_SIZE_EXT, &green_size); + glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_BLUE_SIZE_EXT, &blue_size); + glgsg->_glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_ALPHA_SIZE_EXT, &alpha_size); + _fb_properties.set_color_bits(red_size + green_size + blue_size); + _fb_properties.set_alpha_bits(alpha_size); + } glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, attachpoint, GL_RENDERBUFFER_EXT, _rb[slot]); @@ -962,6 +978,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) { CLP(GraphicsStateGuardian) *glgsg; DCAST_INTO_V(glgsg, _gsg); + if (view >= attach->get_num_views()) { + attach->set_num_views(view + 1); + } + // Create the OpenGL texture object. TextureContext *tc = attach->prepare_now(view, glgsg->get_prepared_objects(), glgsg); nassertv(tc != (TextureContext *)NULL); @@ -985,7 +1005,7 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) { GLenum target = glgsg->get_texture_target(attach->get_texture_type()); if (target == GL_TEXTURE_CUBE_MAP) { target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; - } + } switch (target) { #ifndef OPENGLES_1 @@ -1097,19 +1117,17 @@ set_size(int x, int y) { // Description: Called internally when the window is in // render-to-a-texture mode and we are in the process of // rendering the six faces of a cube map, or any other -// multi-page and/or multi-view texture. This should do -// whatever needs to be done to switch the buffer to the -// indicated page and view. +// multi-page texture. This should do whatever needs +// to be done to switch the buffer to the indicated page. //////////////////////////////////////////////////////////////////// void CLP(GraphicsBuffer):: -select_target_tex_page(int page, int view) { +select_target_tex_page(int page) { nassertv(page >= 0 && page < _fbo.size()); CLP(GraphicsStateGuardian) *glgsg; DCAST_INTO_V(glgsg, _gsg); bool switched_page = (_bound_tex_page != page); - bool switched_view = (_bound_tex_view != view); if (switched_page) { if (_bound_tex_page != -1) { @@ -1123,32 +1141,6 @@ select_target_tex_page(int page, int view) { _bound_tex_page = page; } - if (switched_view || switched_page) { - // We assume that we've already configured the texture earlier - // in bind_bitplanes. Therefore, since we can safely assume that - // all texture views have the same format, we can just bind the - // new view here. - - Texture *tex = _tex[RTP_color]; - if (tex != NULL) { - if (view >= tex->get_num_views()) { - tex->set_num_views(view + 1); - } - - if (GLCAT.is_spam()) { - GLCAT.spam() - << "Binding texture " << *tex - << " view " << view << " to color attachment.\n"; - } - - attach_tex(_bound_tex_page, view, tex, GL_COLOR_ATTACHMENT0_EXT); - - report_my_gl_errors(); - } - - _bound_tex_view = view; - } - report_my_gl_errors(); } @@ -1167,7 +1159,8 @@ open_buffer() { nassertr(_host != 0, false); // Count total color buffers. - int totalcolor = 1 + + int totalcolor = + (_fb_properties.is_stereo() ? 2 : 1) + _fb_properties.get_aux_rgba() + _fb_properties.get_aux_hrgba() + _fb_properties.get_aux_float(); @@ -1229,8 +1222,10 @@ open_buffer() { _fb_properties.set_accum_bits(0); _fb_properties.set_multisamples(_host->get_fb_properties().get_multisamples()); - // Update aux settings to reflect the GL_MAX_DRAW_BUFFERS limit. - int availcolor = glgsg->_max_draw_buffers; + // Update aux settings to reflect the GL_MAX_DRAW_BUFFERS limit, + // if we exceed it, that is. + int availcolor = glgsg->_max_color_targets; + if (totalcolor > availcolor) { int aux_rgba = _fb_properties.get_aux_rgba(); int aux_hrgba = _fb_properties.get_aux_hrgba(); @@ -1238,6 +1233,13 @@ open_buffer() { if (_fb_properties.get_color_bits() > 0 && availcolor > 0) { --availcolor; + if (_fb_properties.is_stereo()) { + if (availcolor > 0) { + --availcolor; + } else { + _fb_properties.set_stereo(0); + } + } } aux_rgba = min(aux_rgba, availcolor); availcolor -= aux_rgba; @@ -1254,7 +1256,6 @@ open_buffer() { _fb_properties.set_back_buffers(0); _fb_properties.set_indexed_color(0); _fb_properties.set_rgb_color(1); - //_fb_properties.set_stereo(0); _fb_properties.set_force_hardware(_host->get_fb_properties().get_force_hardware()); _fb_properties.set_force_software(_host->get_fb_properties().get_force_software()); @@ -1537,21 +1538,28 @@ resolve_multisamples() { #ifndef OPENGLES // Now handle the other color buffers. int next = GL_COLOR_ATTACHMENT1_EXT; - for (int i=0; i<_fb_properties.get_aux_rgba(); i++) { + if (_fb_properties.is_stereo()) { glReadBuffer(next); glDrawBuffer(next); glgsg->_glBlitFramebuffer(0, 0, _rb_size_x, _rb_size_y, 0, 0, _rb_size_x, _rb_size_y, GL_COLOR_BUFFER_BIT, GL_NEAREST); next += 1; } - for (int i=0; i<_fb_properties.get_aux_hrgba(); i++) { + for (int i = 0; i < _fb_properties.get_aux_rgba(); ++i) { glReadBuffer(next); glDrawBuffer(next); glgsg->_glBlitFramebuffer(0, 0, _rb_size_x, _rb_size_y, 0, 0, _rb_size_x, _rb_size_y, GL_COLOR_BUFFER_BIT, GL_NEAREST); next += 1; } - for (int i=0; i<_fb_properties.get_aux_float(); i++) { + for (int i = 0; i < _fb_properties.get_aux_hrgba(); ++i) { + glReadBuffer(next); + glDrawBuffer(next); + glgsg->_glBlitFramebuffer(0, 0, _rb_size_x, _rb_size_y, 0, 0, _rb_size_x, _rb_size_y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + next += 1; + } + for (int i = 0; i < _fb_properties.get_aux_float(); ++i) { glReadBuffer(next); glDrawBuffer(next); glgsg->_glBlitFramebuffer(0, 0, _rb_size_x, _rb_size_y, 0, 0, _rb_size_x, _rb_size_y, diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index bf4c0d0c51..8a161e3e0e 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -74,7 +74,7 @@ public: virtual void set_size(int x, int y); - virtual void select_target_tex_page(int page, int view); + virtual void select_target_tex_page(int page); virtual bool share_depth_buffer(GraphicsOutput *graphics_output); virtual void unshare_depth_buffer(); @@ -94,7 +94,7 @@ protected: private: - void bind_slot(int face, bool rb_resize, Texture **attach, + void bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane plane, GLenum attachpoint); void bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane plane, GLenum attachpoint); @@ -130,7 +130,6 @@ private: // The cube map face we are currently drawing to or have just // finished drawing to, or -1 if we are not drawing to a cube map. int _bound_tex_page; - int _bound_tex_view; bool _initial_clear; bool _needs_rebuild; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 5135fcab92..de1a653b1a 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -49,20 +49,19 @@ #include "load_prc_file.h" #include "bamCache.h" #include "bamCacheRecord.h" -#include "colorWriteAttrib.h" -#include "depthWriteAttrib.h" -#include "shadeModelAttrib.h" -#include "rescaleNormalAttrib.h" -#include "clipPlaneAttrib.h" #include "alphaTestAttrib.h" -#include "cullFaceAttrib.h" -#include "fogAttrib.h" -#include "depthOffsetAttrib.h" -#include "materialAttrib.h" -#include "stencilAttrib.h" -#include "lightAttrib.h" -#include "scissorAttrib.h" #include "clipPlaneAttrib.h" +#include "colorWriteAttrib.h" +#include "cullFaceAttrib.h" +#include "depthOffsetAttrib.h" +#include "depthWriteAttrib.h" +#include "fogAttrib.h" +#include "lightAttrib.h" +#include "materialAttrib.h" +#include "rescaleNormalAttrib.h" +#include "scissorAttrib.h" +#include "shadeModelAttrib.h" +#include "stencilAttrib.h" #include "graphicsEngine.h" #include "shaderGenerator.h" @@ -955,21 +954,23 @@ reset() { // cgGLGetLatestProfile doesn't seem to return anything other // arbvp1/arbfp1 on non-NVIDIA cards, which is severely limiting. - if ((_shader_caps._active_vprofile == CG_PROFILE_ARBVP1 || - _shader_caps._active_fprofile == CG_PROFILE_ARBFP1) && - cgGLIsProfileSupported(CG_PROFILE_GLSLV) && - cgGLIsProfileSupported(CG_PROFILE_GLSLF)) { + // Actually, it seems that these profiles are horribly broken on these + // cards. Let's not do this. + //if ((_shader_caps._active_vprofile == CG_PROFILE_ARBVP1 || + // _shader_caps._active_fprofile == CG_PROFILE_ARBFP1) && + // cgGLIsProfileSupported(CG_PROFILE_GLSLV) && + // cgGLIsProfileSupported(CG_PROFILE_GLSLF)) { - // So, if this happens, we set it to GLSL, which is - // usually supported on all cards. - _shader_caps._active_vprofile = (int)CG_PROFILE_GLSLV; - _shader_caps._active_fprofile = (int)CG_PROFILE_GLSLF; + // // So, if this happens, we set it to GLSL, which is + // // usually supported on all cards. + // _shader_caps._active_vprofile = (int)CG_PROFILE_GLSLV; + // _shader_caps._active_fprofile = (int)CG_PROFILE_GLSLF; #if CG_VERSION_NUM >= 2200 - if (cgGLIsProfileSupported(CG_PROFILE_GLSLG)) { - _shader_caps._active_gprofile = (int)CG_PROFILE_GLSLG; - } + // if (cgGLIsProfileSupported(CG_PROFILE_GLSLG)) { + // _shader_caps._active_gprofile = (int)CG_PROFILE_GLSLG; + // } #endif - } + //} } _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40; _shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40; @@ -1254,12 +1255,12 @@ reset() { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) get_extension_func(GLPREFIX_QUOTED, "DrawBuffersARB"); } - _max_draw_buffers = 1; + + _max_color_targets = 1; if (_glDrawBuffers != 0) { GLint max_draw_buffers = 0; GLP(GetIntegerv)(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); - _max_draw_buffers = max_draw_buffers; - _maximum_simultaneous_render_targets = max_draw_buffers; + _max_color_targets = max_draw_buffers; } #endif // OPENGLES @@ -4200,8 +4201,8 @@ make_geom_munger(const RenderState *state, Thread *current_thread) { // into which to copy. //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: -framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb) { +framebuffer_copy_to_texture(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { nassertr(tex != NULL && dr != NULL, false); set_read_buffer(rb._buffer_type); if (CLP(color_mask)) { @@ -4282,7 +4283,6 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, } } - int view = dr->get_target_tex_view(); TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this); nassertr(tc != (TextureContext *)NULL, false); CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); @@ -4390,8 +4390,8 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, // indicated texture. //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: -framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, - const RenderBuffer &rb) { +framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { nassertr(tex != NULL && dr != NULL, false); set_read_buffer(rb._buffer_type); GLP(PixelStorei)(GL_PACK_ALIGNMENT, 1); @@ -4465,11 +4465,6 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, nassertr(z < tex->get_z_size(), false); - int view = dr->get_target_tex_view(); - if (view >= tex->get_num_views()) { - tex->set_num_views(view + 1); - } - GLenum external_format = get_external_image_format(tex); if (GLCAT.is_spam()) { @@ -5853,27 +5848,37 @@ set_draw_buffer(int rbtype) { if (_current_fbo) { GLuint buffers[16]; - int nbuffers=0; + int nbuffers = 0; int index = 0; if (_current_properties->get_color_bits() > 0) { - if (rbtype & RenderBuffer::T_color) { - buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + (index++); + if (rbtype & RenderBuffer::T_left) { + buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; + } + ++index; + if (_current_properties->is_stereo()) { + if (rbtype & RenderBuffer::T_right) { + buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; + } + ++index; } } for (int i=0; i<_current_properties->get_aux_rgba(); i++) { if (rbtype & (RenderBuffer::T_aux_rgba_0 << i)) { - buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + (index++); + buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; } + ++index; } for (int i=0; i<_current_properties->get_aux_hrgba(); i++) { if (rbtype & (RenderBuffer::T_aux_hrgba_0 << i)) { - buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + (index++); + buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; } + ++index; } for (int i=0; i<_current_properties->get_aux_float(); i++) { if (rbtype & (RenderBuffer::T_aux_float_0 << i)) { - buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + (index++); + buffers[nbuffers++] = GL_COLOR_ATTACHMENT0_EXT + index; } + ++index; } _glDrawBuffers(nbuffers, buffers); @@ -5950,26 +5955,31 @@ set_read_buffer(int rbtype) { } if (_current_fbo) { - GLuint buffer = GL_COLOR_ATTACHMENT0_EXT; int index = 1; + if (_current_properties->is_stereo()) { + if (rbtype & RenderBuffer::T_right) { + buffer = GL_COLOR_ATTACHMENT1_EXT; + } + ++index; + } for (int i=0; i<_current_properties->get_aux_rgba(); i++) { if (rbtype & (RenderBuffer::T_aux_rgba_0 << i)) { buffer = GL_COLOR_ATTACHMENT0_EXT + index; } - index += 1; + ++index; } for (int i=0; i<_current_properties->get_aux_hrgba(); i++) { if (rbtype & (RenderBuffer::T_aux_hrgba_0 << i)) { buffer = GL_COLOR_ATTACHMENT0_EXT + index; } - index += 1; + ++index; } for (int i=0; i<_current_properties->get_aux_float(); i++) { if (rbtype & (RenderBuffer::T_aux_float_0 << i)) { buffer = GL_COLOR_ATTACHMENT0_EXT + index; } - index += 1; + ++index; } GLP(ReadBuffer)(buffer); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index c1aa99f2aa..bba06db847 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -266,9 +266,9 @@ public: virtual void clear(DrawableRegion *region); virtual bool framebuffer_copy_to_texture - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb); + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb); virtual bool framebuffer_copy_to_ram - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb); + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb); void apply_fog(Fog *fog); @@ -637,7 +637,6 @@ public: INLINE bool get_supports_framebuffer_blit(); PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer; PFNGLDRAWBUFFERSPROC _glDrawBuffers; - int _max_draw_buffers; int _max_fb_samples; PFNGLGENQUERIESPROC _glGenQueries; diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 4977be3721..4de1ffca8f 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -208,10 +208,10 @@ public: virtual void end_draw_primitives()=0; virtual bool framebuffer_copy_to_texture - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; virtual bool framebuffer_copy_to_ram - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; - + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; + virtual CoordinateSystem get_internal_coordinate_system() const=0; virtual void bind_light(PointLight *light_obj, const NodePath &light, diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index 3484249744..b607cfe236 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -1350,16 +1350,16 @@ end_draw_primitives() { // copy. //////////////////////////////////////////////////////////////////// bool TinyGraphicsStateGuardian:: -framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, +framebuffer_copy_to_texture(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { nassertr(tex != NULL && dr != NULL, false); - + int xo, yo, w, h; dr->get_region_pixels_i(xo, yo, w, h); tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgba); - int view = dr->get_target_tex_view(); TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this); nassertr(tc != (TextureContext *)NULL, false); TinyTextureContext *gtc = DCAST(TinyTextureContext, tc); @@ -1389,7 +1389,6 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, return true; } - //////////////////////////////////////////////////////////////////// // Function: TinyGraphicsStateGuardian::framebuffer_copy_to_ram // Access: Public, Virtual @@ -1401,10 +1400,11 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, // indicated texture. //////////////////////////////////////////////////////////////////// bool TinyGraphicsStateGuardian:: -framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, +framebuffer_copy_to_ram(Texture *tex, int view, int z, + const DisplayRegion *dr, const RenderBuffer &rb) { nassertr(tex != NULL && dr != NULL, false); - + int xo, yo, w, h; dr->get_region_pixels_i(xo, yo, w, h); @@ -1433,11 +1433,6 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, nassertr(z < tex->get_z_size(), false); - int view = dr->get_target_tex_view(); - if (view >= tex->get_num_views()) { - tex->set_num_views(view + 1); - } - unsigned char *image_ptr = tex->modify_ram_image(); size_t image_size = tex->get_ram_image_size(); if (z >= 0 || view > 0) { diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h index 876fe7b0e4..f9f671866d 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h @@ -82,9 +82,9 @@ public: virtual void end_draw_primitives(); virtual bool framebuffer_copy_to_texture - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb); + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb); virtual bool framebuffer_copy_to_ram - (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb); + (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb); virtual void set_state_and_transform(const RenderState *state, const TransformState *transform); diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.cxx b/panda/src/wgldisplay/wglGraphicsBuffer.cxx index 5a3086e488..5fa7095864 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.cxx +++ b/panda/src/wgldisplay/wglGraphicsBuffer.cxx @@ -214,7 +214,7 @@ bind_texture_to_pbuffer() { // the indicated face. //////////////////////////////////////////////////////////////////// void wglGraphicsBuffer:: -select_target_tex_page(int page, int view) { +select_target_tex_page(int page) { wglGraphicsStateGuardian *wglgsg; DCAST_INTO_V(wglgsg, _gsg); diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.h b/panda/src/wgldisplay/wglGraphicsBuffer.h index 94d7c7cf2d..72aac1247b 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.h +++ b/panda/src/wgldisplay/wglGraphicsBuffer.h @@ -49,7 +49,7 @@ public: virtual bool begin_frame(FrameMode mode, Thread *current_thread); virtual void end_frame(FrameMode mode, Thread *current_thread); - virtual void select_target_tex_page(int page, int view); + virtual void select_target_tex_page(int page); virtual void process_events(); From 566feda34d39319af4aebb608a99ab11787918a8 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 4 Apr 2014 09:23:58 +0000 Subject: [PATCH 20/26] Commit patch by cfsworks to move pgraph stuff to extensions --- makepanda/makepanda.py | 6 +- panda/src/pgraph/Sources.pp | 6 +- panda/src/pgraph/nodePath_ext.I | 16 +- panda/src/pgraph/nodePath_ext.cxx | 2 +- panda/src/pgraph/p3pgraph_ext_composite.cxx | 5 + panda/src/pgraph/pandaNode.cxx | 253 ------------------- panda/src/pgraph/pandaNode.h | 25 +- panda/src/pgraph/pandaNode_ext.cxx | 259 ++++++++++++++++++++ panda/src/pgraph/pandaNode_ext.h | 50 ++++ panda/src/pgraph/renderState.cxx | 159 ------------ panda/src/pgraph/renderState.h | 11 +- panda/src/pgraph/renderState_ext.cxx | 174 +++++++++++++ panda/src/pgraph/renderState_ext.h | 42 ++++ panda/src/pgraph/transformState.cxx | 203 --------------- panda/src/pgraph/transformState.h | 15 +- panda/src/pgraph/transformState_ext.cxx | 214 ++++++++++++++++ panda/src/pgraph/transformState_ext.h | 43 ++++ 17 files changed, 827 insertions(+), 656 deletions(-) create mode 100644 panda/src/pgraph/p3pgraph_ext_composite.cxx create mode 100644 panda/src/pgraph/pandaNode_ext.cxx create mode 100644 panda/src/pgraph/pandaNode_ext.h create mode 100644 panda/src/pgraph/renderState_ext.cxx create mode 100644 panda/src/pgraph/renderState_ext.h create mode 100644 panda/src/pgraph/transformState_ext.cxx create mode 100644 panda/src/pgraph/transformState_ext.h diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index e5376e40ef..684572e620 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -3200,8 +3200,7 @@ if (not RUNTIME): TargetAdd('libp3pgraph.in', opts=OPTS, input=IGATEFILES) TargetAdd('libp3pgraph.in', opts=['IMOD:core', 'ILIB:libp3pgraph', 'SRCDIR:panda/src/pgraph']) TargetAdd('libp3pgraph_igate.obj', input='libp3pgraph.in', opts=["DEPENDENCYONLY","BIGOBJ"]) - TargetAdd('p3pgraph_nodePath_ext.obj', opts=OPTS, input='nodePath_ext.cxx') - TargetAdd('p3pgraph_nodePathCollection_ext.obj', opts=OPTS, input='nodePathCollection_ext.cxx') + TargetAdd('p3pgraph_ext_composite.obj', opts=OPTS, input='p3pgraph_ext_composite.cxx') # # DIRECTORY: panda/src/cull/ @@ -3543,8 +3542,7 @@ if (not RUNTIME): TargetAdd('libpanda.dll', input='p3putil_typedWritable_ext.obj') TargetAdd('libpanda.dll', input='p3pnmimage_pfmFile_ext.obj') TargetAdd('libpanda.dll', input='p3gobj_geomVertexArrayData_ext.obj') - TargetAdd('libpanda.dll', input='p3pgraph_nodePath_ext.obj') - TargetAdd('libpanda.dll', input='p3pgraph_nodePathCollection_ext.obj') + TargetAdd('libpanda.dll', input='p3pgraph_ext_composite.obj') TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian_ext.obj') if PkgSkip("FREETYPE")==0: diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index d0ddb0e0df..5908e7b551 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -116,7 +116,8 @@ #define COMBINED_SOURCES \ $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx \ - $[TARGET]_composite3.cxx $[TARGET]_composite4.cxx + $[TARGET]_composite3.cxx $[TARGET]_composite4.cxx \ + $[TARGET]_ext_composite.cxx #define INCLUDED_SOURCES \ accumulatedAttribs.cxx \ alphaTestAttrib.cxx \ @@ -277,6 +278,7 @@ occluderEffect.I occluderEffect.h \ occluderNode.I occluderNode.h \ pandaNode.I pandaNode.h \ + pandaNode_ext.h pandaNode_ext.cxx \ pandaNodeChain.I pandaNodeChain.h \ planeNode.I planeNode.h \ polylightEffect.I polylightEffect.h \ @@ -289,6 +291,7 @@ renderEffects.I renderEffects.h \ renderModeAttrib.I renderModeAttrib.h \ renderState.I renderState.h \ + renderState_ext.h renderState_ext.cxx \ rescaleNormalAttrib.I rescaleNormalAttrib.h \ sceneGraphReducer.I sceneGraphReducer.h \ sceneSetup.I sceneSetup.h \ @@ -307,6 +310,7 @@ texGenAttrib.I texGenAttrib.h \ textureStageCollection.I textureStageCollection.h \ transformState.I transformState.h \ + transformState_ext.h transformState_ext.cxx \ transparencyAttrib.I transparencyAttrib.h \ weakNodePath.I weakNodePath.h \ workingNodePath.I workingNodePath.h diff --git a/panda/src/pgraph/nodePath_ext.I b/panda/src/pgraph/nodePath_ext.I index a97a29fb59..3888d6f8f2 100644 --- a/panda/src/pgraph/nodePath_ext.I +++ b/panda/src/pgraph/nodePath_ext.I @@ -12,6 +12,8 @@ // //////////////////////////////////////////////////////////////////// +#include "pandaNode_ext.h" + #ifndef CPPPARSER #ifdef STDFLOAT_DOUBLE IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3d; @@ -33,7 +35,7 @@ IMPORT_THIS struct Dtool_PyTypedObject Dtool_LPoint3f; INLINE void Extension:: get_python_tag_keys(vector_string &keys) const { nassertv_always(!_this->is_empty()); - _this->node()->get_python_tag_keys(keys); + invoke_extension(_this->node()).get_python_tag_keys(keys); } //////////////////////////////////////////////////////////////////// @@ -49,7 +51,7 @@ get_tag_keys() const { Py_INCREF(Py_None); return Py_None; } - return _this->node()->get_tag_keys(); + return invoke_extension(_this->node()).get_tag_keys(); } //////////////////////////////////////////////////////////////////// @@ -66,7 +68,7 @@ get_python_tag_keys() const { Py_INCREF(Py_None); return Py_None; } - return _this->node()->get_python_tag_keys(); + return invoke_extension(_this->node()).get_python_tag_keys(); } //////////////////////////////////////////////////////////////////// @@ -85,7 +87,7 @@ get_python_tag_keys() const { INLINE void Extension:: set_python_tag(const string &key, PyObject *value) { nassertv_always(!_this->is_empty()); - _this->node()->set_python_tag(key, value); + invoke_extension(_this->node()).set_python_tag(key, value); } //////////////////////////////////////////////////////////////////// @@ -104,7 +106,7 @@ get_python_tag(const string &key) const { Py_INCREF(Py_None); return Py_None; } - return _this->node()->get_python_tag(key); + return invoke_extension(_this->node()).get_python_tag(key); } //////////////////////////////////////////////////////////////////// @@ -122,7 +124,7 @@ has_python_tag(const string &key) const { if (_this->is_empty()) { return false; } - return _this->node()->has_python_tag(key); + return invoke_extension(_this->node()).has_python_tag(key); } //////////////////////////////////////////////////////////////////// @@ -136,7 +138,7 @@ has_python_tag(const string &key) const { INLINE void Extension:: clear_python_tag(const string &key) { nassertv_always(!_this->is_empty()); - _this->node()->clear_python_tag(key); + invoke_extension(_this->node()).clear_python_tag(key); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx index da66754c42..0a9b570194 100644 --- a/panda/src/pgraph/nodePath_ext.cxx +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -40,7 +40,7 @@ __copy__() const { // If we do have a node, duplicate it, and wrap it in a new // NodePath. - return NodePath(_this->node()->__copy__()); + return NodePath(invoke_extension(_this->node()).__copy__()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/p3pgraph_ext_composite.cxx b/panda/src/pgraph/p3pgraph_ext_composite.cxx new file mode 100644 index 0000000000..6dc854b914 --- /dev/null +++ b/panda/src/pgraph/p3pgraph_ext_composite.cxx @@ -0,0 +1,5 @@ +#include "nodePath_ext.cxx" +#include "nodePathCollection_ext.cxx" +#include "pandaNode_ext.cxx" +#include "renderState_ext.cxx" +#include "transformState_ext.cxx" diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index ec4a2c4639..2dd7f5a5b6 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -632,73 +632,6 @@ copy_subgraph(Thread *current_thread) const { return r_copy_subgraph(inst_map, current_thread); } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::__copy__ -// Access: Published -// Description: A special Python method that is invoked by -// copy.copy(node). Unlike the PandaNode copy -// constructor, which creates a new node without -// children, this shares child pointers (essentially -// making every child an instance). This is intended to -// simulate the behavior of copy.copy() for other -// objects. -//////////////////////////////////////////////////////////////////// -PT(PandaNode) PandaNode:: -__copy__() const { - Thread *current_thread = Thread::get_current_thread(); - - PT(PandaNode) node_dupe = make_copy(); - - Children children = get_children(current_thread); - int num_children = children.get_num_children(); - - for (int i = 0; i < num_children; ++i) { - node_dupe->add_child(children.get_child(i), children.get_child_sort(i)); - } - - return node_dupe; -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::__deepcopy__ -// Access: Published -// Description: A special Python method that is invoked by -// copy.deepcopy(node). This calls copy_subgraph() -// unless the node is already present in the provided -// dictionary. -//////////////////////////////////////////////////////////////////// -PyObject *PandaNode:: -__deepcopy__(PyObject *self, PyObject *memo) const { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode; - - // Borrowed reference. - PyObject *dupe = PyDict_GetItem(memo, self); - if (dupe != NULL) { - // Already in the memo dictionary. - Py_INCREF(dupe); - return dupe; - } - - PT(PandaNode) node_dupe = copy_subgraph(); - - // DTool_CreatePyInstanceTyped() steals a C++ reference. - node_dupe->ref(); - dupe = DTool_CreatePyInstanceTyped - ((void *)node_dupe.p(), Dtool_PandaNode, true, false, - node_dupe->get_type_index()); - - if (PyDict_SetItem(memo, self, dupe) != 0) { - Py_DECREF(dupe); - return NULL; - } - - return dupe; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: PandaNode::count_num_descendants // Access: Published @@ -1509,118 +1442,6 @@ clear_tag(const string &key, Thread *current_thread) { mark_bam_modified(); } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::set_python_tag -// Access: Published -// Description: Associates an arbitrary Python object with a -// user-defined key which is stored on the node. This -// is similar to set_tag(), except it can store any -// Python object instead of just a string. However, the -// Python object is not recorded to a bam file. -// -// Each unique key stores a different string value. -// There is no effective limit on the number of -// different keys that may be stored or on the length of -// any one key's value. -//////////////////////////////////////////////////////////////////// -void PandaNode:: -set_python_tag(const string &key, PyObject *value) { - Thread *current_thread = Thread::get_current_thread(); - int pipeline_stage = current_thread->get_pipeline_stage(); - nassertv(pipeline_stage == 0); - - CDWriter cdata(_cycler); - Py_XINCREF(value); - - pair result; - result = cdata->_python_tag_data.insert(PythonTagData::value_type(key, value)); - - if (!result.second) { - // The insert was unsuccessful; that means the key was already - // present in the map. In this case, we should decrement the - // original value's reference count and replace it with the new - // object. - PythonTagData::iterator ti = result.first; - PyObject *old_value = (*ti).second; - Py_XDECREF(old_value); - (*ti).second = value; - } - - // Even though the python tag isn't recorded in the bam stream? - mark_bam_modified(); -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::get_python_tag -// Access: Published -// Description: Retrieves the Python object that was previously -// set on this node for the particular key, if any. If -// no value has been previously set, returns None. -//////////////////////////////////////////////////////////////////// -PyObject *PandaNode:: -get_python_tag(const string &key) const { - CDReader cdata(_cycler); - PythonTagData::const_iterator ti; - ti = cdata->_python_tag_data.find(key); - if (ti != cdata->_python_tag_data.end()) { - PyObject *result = (*ti).second; - Py_XINCREF(result); - return result; - } - Py_INCREF(Py_None); - return Py_None; -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::has_python_tag -// Access: Published -// Description: Returns true if a Python object has been defined on -// this node for the particular key (even if that object -// is None), or false if no object has been set. -//////////////////////////////////////////////////////////////////// -bool PandaNode:: -has_python_tag(const string &key) const { - CDReader cdata(_cycler); - PythonTagData::const_iterator ti; - ti = cdata->_python_tag_data.find(key); - return (ti != cdata->_python_tag_data.end()); -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::clear_python_tag -// Access: Published -// Description: Removes the Python object defined for this key on -// this particular node. After a call to -// clear_python_tag(), has_python_tag() will return -// false for the indicated key. -//////////////////////////////////////////////////////////////////// -void PandaNode:: -clear_python_tag(const string &key) { - Thread *current_thread = Thread::get_current_thread(); - int pipeline_stage = current_thread->get_pipeline_stage(); - nassertv(pipeline_stage == 0); - - CDWriter cdata(_cycler, current_thread); - PythonTagData::iterator ti; - ti = cdata->_python_tag_data.find(key); - if (ti != cdata->_python_tag_data.end()) { - PyObject *value = (*ti).second; - Py_XDECREF(value); - cdata->_python_tag_data.erase(ti); - } - - // Even though the python tag isn't recorded in the bam stream? - mark_bam_modified(); -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: PandaNode::copy_tags // Access: Published @@ -1743,80 +1564,6 @@ get_tag_keys(vector_string &keys) const { } } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: Filename::get_python_tag_keys -// Access: Published -// Description: Fills the given vector up with the -// list of Python tags on this PandaNode. -// -// It is the user's responsibility to ensure that the -// keys vector is empty before making this call; -// otherwise, the new files will be appended to it. -//////////////////////////////////////////////////////////////////// -void PandaNode:: -get_python_tag_keys(vector_string &keys) const { - CDReader cdata(_cycler); - if (!cdata->_python_tag_data.empty()) { - PythonTagData::const_iterator ti = cdata->_python_tag_data.begin(); - while (ti != cdata->_python_tag_data.end()) { - keys.push_back((*ti).first); - ++ti; - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: Filename::get_tag_keys -// Access: Published -// Description: This variant on get_tag_keys returns -// a Python list of strings. -//////////////////////////////////////////////////////////////////// -PyObject *PandaNode:: -get_tag_keys() const { - vector_string keys; - get_tag_keys(keys); - - PyObject *result = PyList_New(keys.size()); - for (size_t i = 0; i < keys.size(); ++i) { - const string &tag_name = keys[i]; -#if PY_MAJOR_VERSION >= 3 - PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size()); -#else - PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size()); -#endif - PyList_SET_ITEM(result, i, str); - } - - return result; -} - -//////////////////////////////////////////////////////////////////// -// Function: Filename::get_python_tag_keys -// Access: Published -// Description: This variant on get_python_tag_keys returns -// a Python list of strings. -//////////////////////////////////////////////////////////////////// -PyObject *PandaNode:: -get_python_tag_keys() const { - vector_string keys; - get_python_tag_keys(keys); - - PyObject *result = PyList_New(keys.size()); - for (size_t i = 0; i < keys.size(); ++i) { - const string &tag_name = keys[i]; -#if PY_MAJOR_VERSION >= 3 - PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size()); -#else - PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size()); -#endif - PyList_SET_ITEM(result, i, str); - } - - return result; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: PandaNode::compare_tags // Access: Published diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 5970d086dd..17d93d8248 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -45,6 +45,7 @@ #include "copyOnWriteObject.h" #include "copyOnWritePointer.h" #include "lightReMutex.h" +#include "extension.h" #ifdef HAVE_PYTHON @@ -118,10 +119,8 @@ PUBLISHED: virtual PandaNode *make_copy() const; PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const; -#ifdef HAVE_PYTHON - PT(PandaNode) __copy__() const; - PyObject *__deepcopy__(PyObject *self, PyObject *memo) const; -#endif + EXTENSION(PT(PandaNode) __copy__() const); + EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const); INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const; INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const; @@ -202,16 +201,15 @@ PUBLISHED: void clear_tag(const string &key, Thread *current_thread = Thread::get_current_thread()); void get_tag_keys(vector_string &keys) const; -#ifdef HAVE_PYTHON - PyObject *get_tag_keys() const; - void set_python_tag(const string &key, PyObject *value); - PyObject *get_python_tag(const string &key) const; - bool has_python_tag(const string &key) const; - void clear_python_tag(const string &key); - void get_python_tag_keys(vector_string &keys) const; - PyObject *get_python_tag_keys() const; -#endif // HAVE_PYTHON + EXTENSION(PyObject *get_tag_keys() const); + + EXTENSION(void set_python_tag(const string &key, PyObject *value)); + EXTENSION(PyObject *get_python_tag(const string &key) const); + EXTENSION(bool has_python_tag(const string &key) const); + EXTENSION(void clear_python_tag(const string &key)); + EXTENSION(void get_python_tag_keys(vector_string &keys) const); + EXTENSION(PyObject *get_python_tag_keys() const); INLINE bool has_tags() const; void copy_tags(PandaNode *other); @@ -784,6 +782,7 @@ private: friend class WorkingNodePath; friend class PandaNodePipelineReader; friend class EggLoader; + friend class Extension; }; //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/pandaNode_ext.cxx b/panda/src/pgraph/pandaNode_ext.cxx new file mode 100644 index 0000000000..515b704574 --- /dev/null +++ b/panda/src/pgraph/pandaNode_ext.cxx @@ -0,0 +1,259 @@ +// Filename: pandaNode_ext.cxx +// Created by: CFSworks (30Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#include "pandaNode_ext.h" + +#ifdef HAVE_PYTHON + +//////////////////////////////////////////////////////////////////// +// Function: Extension::__copy__ +// Access: Published +// Description: A special Python method that is invoked by +// copy.copy(node). Unlike the PandaNode copy +// constructor, which creates a new node without +// children, this shares child pointers (essentially +// making every child an instance). This is intended to +// simulate the behavior of copy.copy() for other +// objects. +//////////////////////////////////////////////////////////////////// +PT(PandaNode) Extension:: +__copy__() const { + Thread *current_thread = Thread::get_current_thread(); + + PT(PandaNode) node_dupe = _this->make_copy(); + + PandaNode::Children children = _this->get_children(current_thread); + int num_children = children.get_num_children(); + + for (int i = 0; i < num_children; ++i) { + node_dupe->add_child(children.get_child(i), children.get_child_sort(i)); + } + + return node_dupe; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::__deepcopy__ +// Access: Published +// Description: A special Python method that is invoked by +// copy.deepcopy(node). This calls copy_subgraph() +// unless the node is already present in the provided +// dictionary. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +__deepcopy__(PyObject *self, PyObject *memo) const { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode; + + // Borrowed reference. + PyObject *dupe = PyDict_GetItem(memo, self); + if (dupe != NULL) { + // Already in the memo dictionary. + Py_INCREF(dupe); + return dupe; + } + + PT(PandaNode) node_dupe = _this->copy_subgraph(); + + // DTool_CreatePyInstanceTyped() steals a C++ reference. + node_dupe->ref(); + dupe = DTool_CreatePyInstanceTyped + ((void *)node_dupe.p(), Dtool_PandaNode, true, false, + node_dupe->get_type_index()); + + if (PyDict_SetItem(memo, self, dupe) != 0) { + Py_DECREF(dupe); + return NULL; + } + + return dupe; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::set_python_tag +// Access: Published +// Description: Associates an arbitrary Python object with a +// user-defined key which is stored on the node. This +// is similar to set_tag(), except it can store any +// Python object instead of just a string. However, the +// Python object is not recorded to a bam file. +// +// Each unique key stores a different string value. +// There is no effective limit on the number of +// different keys that may be stored or on the length of +// any one key's value. +//////////////////////////////////////////////////////////////////// +void Extension:: +set_python_tag(const string &key, PyObject *value) { + Thread *current_thread = Thread::get_current_thread(); + int pipeline_stage = current_thread->get_pipeline_stage(); + nassertv(pipeline_stage == 0); + + PandaNode::CDWriter cdata(_this->_cycler); + Py_XINCREF(value); + + pair result; + result = cdata->_python_tag_data.insert(PandaNode::PythonTagData::value_type(key, value)); + + if (!result.second) { + // The insert was unsuccessful; that means the key was already + // present in the map. In this case, we should decrement the + // original value's reference count and replace it with the new + // object. + PandaNode::PythonTagData::iterator ti = result.first; + PyObject *old_value = (*ti).second; + Py_XDECREF(old_value); + (*ti).second = value; + } + + // Even though the python tag isn't recorded in the bam stream? + _this->mark_bam_modified(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_python_tag +// Access: Published +// Description: Retrieves the Python object that was previously +// set on this node for the particular key, if any. If +// no value has been previously set, returns None. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_python_tag(const string &key) const { + PandaNode::CDReader cdata(_this->_cycler); + PandaNode::PythonTagData::const_iterator ti; + ti = cdata->_python_tag_data.find(key); + if (ti != cdata->_python_tag_data.end()) { + PyObject *result = (*ti).second; + Py_XINCREF(result); + return result; + } + Py_INCREF(Py_None); + return Py_None; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::has_python_tag +// Access: Published +// Description: Returns true if a Python object has been defined on +// this node for the particular key (even if that object +// is None), or false if no object has been set. +//////////////////////////////////////////////////////////////////// +bool Extension:: +has_python_tag(const string &key) const { + PandaNode::CDReader cdata(_this->_cycler); + PandaNode::PythonTagData::const_iterator ti; + ti = cdata->_python_tag_data.find(key); + return (ti != cdata->_python_tag_data.end()); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::clear_python_tag +// Access: Published +// Description: Removes the Python object defined for this key on +// this particular node. After a call to +// clear_python_tag(), has_python_tag() will return +// false for the indicated key. +//////////////////////////////////////////////////////////////////// +void Extension:: +clear_python_tag(const string &key) { + Thread *current_thread = Thread::get_current_thread(); + int pipeline_stage = current_thread->get_pipeline_stage(); + nassertv(pipeline_stage == 0); + + PandaNode::CDWriter cdata(_this->_cycler, current_thread); + PandaNode::PythonTagData::iterator ti; + ti = cdata->_python_tag_data.find(key); + if (ti != cdata->_python_tag_data.end()) { + PyObject *value = (*ti).second; + Py_XDECREF(value); + cdata->_python_tag_data.erase(ti); + } + + // Even though the python tag isn't recorded in the bam stream? + _this->mark_bam_modified(); +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_python_tag_keys +// Access: Published +// Description: Fills the given vector up with the +// list of Python tags on this PandaNode. +// +// It is the user's responsibility to ensure that the +// keys vector is empty before making this call; +// otherwise, the new files will be appended to it. +//////////////////////////////////////////////////////////////////// +void Extension:: +get_python_tag_keys(vector_string &keys) const { + PandaNode::CDReader cdata(_this->_cycler); + if (!cdata->_python_tag_data.empty()) { + PandaNode::PythonTagData::const_iterator ti = cdata->_python_tag_data.begin(); + while (ti != cdata->_python_tag_data.end()) { + keys.push_back((*ti).first); + ++ti; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_tag_keys +// Access: Published +// Description: This variant on get_tag_keys returns +// a Python list of strings. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_tag_keys() const { + vector_string keys; + _this->get_tag_keys(keys); + + PyObject *result = PyList_New(keys.size()); + for (size_t i = 0; i < keys.size(); ++i) { + const string &tag_name = keys[i]; +#if PY_MAJOR_VERSION >= 3 + PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size()); +#else + PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size()); +#endif + PyList_SET_ITEM(result, i, str); + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_python_tag_keys +// Access: Published +// Description: This variant on get_python_tag_keys returns +// a Python list of strings. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_python_tag_keys() const { + vector_string keys; + get_python_tag_keys(keys); + + PyObject *result = PyList_New(keys.size()); + for (size_t i = 0; i < keys.size(); ++i) { + const string &tag_name = keys[i]; +#if PY_MAJOR_VERSION >= 3 + PyObject *str = PyUnicode_FromStringAndSize(tag_name.data(), tag_name.size()); +#else + PyObject *str = PyString_FromStringAndSize(tag_name.data(), tag_name.size()); +#endif + PyList_SET_ITEM(result, i, str); + } + + return result; +} + +#endif // HAVE_PYTHON + diff --git a/panda/src/pgraph/pandaNode_ext.h b/panda/src/pgraph/pandaNode_ext.h new file mode 100644 index 0000000000..a19dc50db9 --- /dev/null +++ b/panda/src/pgraph/pandaNode_ext.h @@ -0,0 +1,50 @@ +// Filename: pandaNode_ext.h +// Created by: CFSworks (30Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef PANDANODE_EXT_H +#define PANDANODE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "pandaNode.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// PandaNode, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PT(PandaNode) __copy__() const; + PyObject *__deepcopy__(PyObject *self, PyObject *memo) const; + + PyObject *get_tag_keys() const; + + void set_python_tag(const string &key, PyObject *value); + PyObject *get_python_tag(const string &key) const; + bool has_python_tag(const string &key) const; + void clear_python_tag(const string &key); + void get_python_tag_keys(vector_string &keys) const; + PyObject *get_python_tag_keys() const; +}; + +#endif // HAVE_PYTHON + +#endif // PANDANODE_EXT_H diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 27bdb08cff..d417221be8 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -733,126 +733,6 @@ unref() const { return false; } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: RenderState::get_composition_cache -// Access: Published -// Description: 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 *RenderState:: -get_composition_cache() const { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState; - LightReMutexHolder holder(*_states_lock); - size_t cache_size = _composition_cache.get_size(); - PyObject *list = PyList_New(cache_size); - - for (size_t i = 0; i < cache_size; ++i) { - PyObject *tuple = PyTuple_New(2); - PyObject *a, *b; - if (!_composition_cache.has_element(i)) { - a = Py_None; - Py_INCREF(a); - b = Py_None; - Py_INCREF(b); - } else { - const RenderState *source = _composition_cache.get_key(i); - if (source == (RenderState *)NULL) { - 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 = _composition_cache.get_data(i)._result; - if (result == (RenderState *)NULL) { - 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; -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: RenderState::get_invert_composition_cache -// Access: Published -// Description: 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 *RenderState:: -get_invert_composition_cache() const { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState; - LightReMutexHolder holder(*_states_lock); - size_t cache_size = _invert_composition_cache.get_size(); - PyObject *list = PyList_New(cache_size); - - for (size_t i = 0; i < cache_size; ++i) { - PyObject *tuple = PyTuple_New(2); - PyObject *a, *b; - if (!_invert_composition_cache.has_element(i)) { - a = Py_None; - Py_INCREF(a); - b = Py_None; - Py_INCREF(b); - } else { - const RenderState *source = _invert_composition_cache.get_key(i); - if (source == (RenderState *)NULL) { - 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 = _invert_composition_cache.get_data(i)._result; - if (result == (RenderState *)NULL) { - 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; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: RenderState::get_auto_shader_state // Access: Published @@ -2271,45 +2151,6 @@ update_pstats(int old_referenced_bits, int new_referenced_bits) { #endif // DO_PSTATS } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: RenderState::get_states -// Access: Published, Static -// Description: Returns a list of all of the RenderState objects -// in the state cache. The order of elements in this -// cache is arbitrary. -//////////////////////////////////////////////////////////////////// -PyObject *RenderState:: -get_states() { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState; - if (_states == (States *)NULL) { - return PyList_New(0); - } - LightReMutexHolder holder(*_states_lock); - - size_t num_states = _states->get_num_entries(); - PyObject *list = PyList_New(num_states); - size_t i = 0; - - int size = _states->get_size(); - for (int si = 0; si < size; ++si) { - if (!_states->has_element(si)) { - continue; - } - const RenderState *state = _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; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: RenderState::init_states // Access: Public, Static diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 8c5fc27a8b..0100049c1c 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -126,10 +126,8 @@ PUBLISHED: INLINE int get_invert_composition_cache_size() const; INLINE const RenderState *get_invert_composition_cache_source(int n) const; INLINE const RenderState *get_invert_composition_cache_result(int n) const; -#ifdef HAVE_PYTHON - PyObject *get_composition_cache() const; - PyObject *get_invert_composition_cache() const; -#endif // HAVE_PYTHON + EXTENSION(PyObject *get_composition_cache() const); + EXTENSION(PyObject *get_invert_composition_cache() const); const RenderState *get_auto_shader_state() const; @@ -146,9 +144,7 @@ PUBLISHED: static void list_cycles(ostream &out); static void list_states(ostream &out); static bool validate_states(); -#ifdef HAVE_PYTHON - static PyObject *get_states(); -#endif // HAVE_PYTHON + EXTENSION(static PyObject *get_states()); PUBLISHED: // These methods are intended for use by low-level code, but they're @@ -363,6 +359,7 @@ private: friend class GraphicsStateGuardian; friend class RenderAttribRegistry; + friend class Extension; }; INLINE ostream &operator << (ostream &out, const RenderState &state) { diff --git a/panda/src/pgraph/renderState_ext.cxx b/panda/src/pgraph/renderState_ext.cxx new file mode 100644 index 0000000000..70b214fbb3 --- /dev/null +++ b/panda/src/pgraph/renderState_ext.cxx @@ -0,0 +1,174 @@ +// Filename: renderState_ext.cxx +// Created by: CFSworks (31Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#include "renderState_ext.h" + +#ifdef HAVE_PYTHON + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_composition_cache +// Access: Published +// Description: 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 { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState; + LightReMutexHolder holder(*RenderState::_states_lock); + size_t cache_size = _this->_composition_cache.get_size(); + PyObject *list = PyList_New(cache_size); + + for (size_t i = 0; i < cache_size; ++i) { + PyObject *tuple = PyTuple_New(2); + PyObject *a, *b; + if (!_this->_composition_cache.has_element(i)) { + a = Py_None; + Py_INCREF(a); + b = Py_None; + Py_INCREF(b); + } else { + const RenderState *source = _this->_composition_cache.get_key(i); + if (source == (RenderState *)NULL) { + 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 == (RenderState *)NULL) { + 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; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_invert_composition_cache +// Access: Published +// Description: 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 { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState; + LightReMutexHolder holder(*RenderState::_states_lock); + size_t cache_size = _this->_invert_composition_cache.get_size(); + PyObject *list = PyList_New(cache_size); + + for (size_t i = 0; i < cache_size; ++i) { + PyObject *tuple = PyTuple_New(2); + PyObject *a, *b; + if (!_this->_invert_composition_cache.has_element(i)) { + a = Py_None; + Py_INCREF(a); + b = Py_None; + Py_INCREF(b); + } else { + const RenderState *source = _this->_invert_composition_cache.get_key(i); + if (source == (RenderState *)NULL) { + 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 == (RenderState *)NULL) { + 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; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_states +// Access: Published, Static +// Description: 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() { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState; + if (RenderState::_states == (RenderState::States *)NULL) { + return PyList_New(0); + } + LightReMutexHolder holder(*RenderState::_states_lock); + + size_t num_states = RenderState::_states->get_num_entries(); + PyObject *list = PyList_New(num_states); + size_t i = 0; + + int size = RenderState::_states->get_size(); + for (int si = 0; si < size; ++si) { + if (!RenderState::_states->has_element(si)) { + continue; + } + 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; +} + + + +#endif // HAVE_PYTHON diff --git a/panda/src/pgraph/renderState_ext.h b/panda/src/pgraph/renderState_ext.h new file mode 100644 index 0000000000..43830e8021 --- /dev/null +++ b/panda/src/pgraph/renderState_ext.h @@ -0,0 +1,42 @@ +// Filename: renderState_ext.h +// Created by: CFSworks (31Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef RENDERSTATE_EXT_H +#define RENDERSTATE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "renderState.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// RenderState, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_composition_cache() const; + PyObject *get_invert_composition_cache() const; + static PyObject *get_states(); +}; + +#endif // HAVE_PYTHON + +#endif // RENDERSTATE_EXT_H diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index e990cca0f1..84fa387080 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -818,134 +818,6 @@ validate_composition_cache() const { return true; } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: TransformState::get_composition_cache -// Access: Published -// Description: Returns a list of 2-tuples that represents the -// composition cache. For each tuple in the list, the -// first element is the source transform, and the second -// is the result transform. 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 *TransformState:: -get_composition_cache() const { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; - LightReMutexHolder holder(*_states_lock); - - size_t num_states = _composition_cache.get_num_entries(); - PyObject *list = PyList_New(num_states); - size_t i = 0; - - int size = _composition_cache.get_size(); - for (int si = 0; si < size; ++si) { - if (!_composition_cache.has_element(si)) { - continue; - } - - PyObject *tuple = PyTuple_New(2); - PyObject *a, *b; - - const TransformState *source = _composition_cache.get_key(si); - if (source == (TransformState *)NULL) { - a = Py_None; - Py_INCREF(a); - } else { - source->ref(); - a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, - true, true, source->get_type_index()); - } - const TransformState *result = _composition_cache.get_data(si)._result; - if (result == (TransformState *)NULL) { - b = Py_None; - Py_INCREF(b); - } else { - result->ref(); - b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, - true, true, result->get_type_index()); - } - - PyTuple_SET_ITEM(tuple, 0, a); - PyTuple_SET_ITEM(tuple, 1, b); - - nassertr(i < num_states, list); - PyList_SET_ITEM(list, i, tuple); - ++i; - } - nassertr(i == num_states, list); - return list; -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: TransformState::get_invert_composition_cache -// Access: Published -// Description: Returns a list of 2-tuples that represents the -// invert_composition cache. For each tuple in the list, the -// first element is the source transform, and the second -// is the result transform. 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 *TransformState:: -get_invert_composition_cache() const { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; - LightReMutexHolder holder(*_states_lock); - - size_t num_states = _invert_composition_cache.get_num_entries(); - PyObject *list = PyList_New(num_states); - size_t i = 0; - - int size = _invert_composition_cache.get_size(); - for (int si = 0; si < size; ++si) { - if (!_invert_composition_cache.has_element(si)) { - continue; - } - - PyObject *tuple = PyTuple_New(2); - PyObject *a, *b; - - const TransformState *source = _invert_composition_cache.get_key(si); - if (source == (TransformState *)NULL) { - a = Py_None; - Py_INCREF(a); - } else { - source->ref(); - a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, - true, true, source->get_type_index()); - } - const TransformState *result = _invert_composition_cache.get_data(si)._result; - if (result == (TransformState *)NULL) { - b = Py_None; - Py_INCREF(b); - } else { - result->ref(); - b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, - true, true, result->get_type_index()); - } - - PyTuple_SET_ITEM(tuple, 0, a); - PyTuple_SET_ITEM(tuple, 1, b); - - nassertr(i < num_states, list); - PyList_SET_ITEM(list, i, tuple); - ++i; - } - nassertr(i == num_states, list); - return list; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: TransformState::output // Access: Published @@ -1529,81 +1401,6 @@ validate_states() { return true; } -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: TransformState::get_states -// Access: Published, Static -// Description: Returns a list of all of the TransformState objects -// in the state cache. The order of elements in this -// cache is arbitrary. -//////////////////////////////////////////////////////////////////// -PyObject *TransformState:: -get_states() { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; - if (_states == (States *)NULL) { - return PyList_New(0); - } - LightReMutexHolder holder(*_states_lock); - - size_t num_states = _states->get_num_entries(); - PyObject *list = PyList_New(num_states); - size_t i = 0; - - int size = _states->get_size(); - for (int si = 0; si < size; ++si) { - if (!_states->has_element(si)) { - continue; - } - const TransformState *state = _states->get_key(si); - state->ref(); - PyObject *a = - DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState, - 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; -} -#endif // HAVE_PYTHON - -#ifdef HAVE_PYTHON -//////////////////////////////////////////////////////////////////// -// Function: TransformState::get_unused_states -// Access: Published, Static -// Description: Returns a list of all of the "unused" TransformState -// objects in the state cache. See -// get_num_unused_states(). -//////////////////////////////////////////////////////////////////// -PyObject *TransformState:: -get_unused_states() { - IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; - if (_states == (States *)NULL) { - return PyList_New(0); - } - LightReMutexHolder holder(*_states_lock); - - PyObject *list = PyList_New(0); - int size = _states->get_size(); - for (int si = 0; si < size; ++si) { - if (!_states->has_element(si)) { - continue; - } - const TransformState *state = _states->get_key(si); - if (state->get_cache_ref_count() == state->get_ref_count()) { - state->ref(); - PyObject *a = - DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState, - true, true, state->get_type_index()); - PyList_Append(list, a); - Py_DECREF(a); - } - } - return list; -} -#endif // HAVE_PYTHON - //////////////////////////////////////////////////////////////////// // Function: TransformState::init_states // Access: Public, Static diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 915eb7f504..e6e3223cb9 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -32,6 +32,7 @@ #include "deletedChain.h" #include "simpleHashMap.h" #include "cacheStats.h" +#include "extension.h" class GraphicsStateGuardianBase; class FactoryParams; @@ -190,10 +191,8 @@ PUBLISHED: INLINE const TransformState *get_invert_composition_cache_source(int n) const; INLINE const TransformState *get_invert_composition_cache_result(int n) const; bool validate_composition_cache() const; -#ifdef HAVE_PYTHON - PyObject *get_composition_cache() const; - PyObject *get_invert_composition_cache() const; -#endif // HAVE_PYTHON + EXTENSION(PyObject *get_composition_cache() const); + EXTENSION(PyObject *get_invert_composition_cache() const); void output(ostream &out) const; void write(ostream &out, int indent_level) const; @@ -206,10 +205,8 @@ PUBLISHED: static void list_cycles(ostream &out); static void list_states(ostream &out); static bool validate_states(); -#ifdef HAVE_PYTHON - static PyObject *get_states(); - static PyObject *get_unused_states(); -#endif // HAVE_PYTHON + EXTENSION(static PyObject *get_states()); + EXTENSION(static PyObject *get_unused_states()); public: @@ -405,6 +402,8 @@ public: private: static TypeHandle _type_handle; + + friend class Extension; }; INLINE ostream &operator << (ostream &out, const TransformState &state) { diff --git a/panda/src/pgraph/transformState_ext.cxx b/panda/src/pgraph/transformState_ext.cxx new file mode 100644 index 0000000000..c66fd87943 --- /dev/null +++ b/panda/src/pgraph/transformState_ext.cxx @@ -0,0 +1,214 @@ +// Filename: transformState_ext.cxx +// Created by: CFSworks (30Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#include "transformState_ext.h" + +#ifdef HAVE_PYTHON + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_composition_cache +// Access: Published +// Description: Returns a list of 2-tuples that represents the +// composition cache. For each tuple in the list, the +// first element is the source transform, and the second +// is the result transform. 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 { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; + LightReMutexHolder holder(*_this->_states_lock); + + size_t num_states = _this->_composition_cache.get_num_entries(); + PyObject *list = PyList_New(num_states); + size_t i = 0; + + int size = _this->_composition_cache.get_size(); + for (int si = 0; si < size; ++si) { + if (!_this->_composition_cache.has_element(si)) { + continue; + } + + PyObject *tuple = PyTuple_New(2); + PyObject *a, *b; + + const TransformState *source = _this->_composition_cache.get_key(si); + if (source == (TransformState *)NULL) { + a = Py_None; + Py_INCREF(a); + } else { + source->ref(); + a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, + true, true, source->get_type_index()); + } + const TransformState *result = _this->_composition_cache.get_data(si)._result; + if (result == (TransformState *)NULL) { + b = Py_None; + Py_INCREF(b); + } else { + result->ref(); + b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, + true, true, result->get_type_index()); + } + + PyTuple_SET_ITEM(tuple, 0, a); + PyTuple_SET_ITEM(tuple, 1, b); + + nassertr(i < num_states, list); + PyList_SET_ITEM(list, i, tuple); + ++i; + } + nassertr(i == num_states, list); + return list; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_invert_composition_cache +// Access: Published +// Description: Returns a list of 2-tuples that represents the +// invert_composition cache. For each tuple in the list, the +// first element is the source transform, and the second +// is the result transform. 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 { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; + LightReMutexHolder holder(*_this->_states_lock); + + size_t num_states = _this->_invert_composition_cache.get_num_entries(); + PyObject *list = PyList_New(num_states); + size_t i = 0; + + int size = _this->_invert_composition_cache.get_size(); + for (int si = 0; si < size; ++si) { + if (!_this->_invert_composition_cache.has_element(si)) { + continue; + } + + PyObject *tuple = PyTuple_New(2); + PyObject *a, *b; + + const TransformState *source = _this->_invert_composition_cache.get_key(si); + if (source == (TransformState *)NULL) { + a = Py_None; + Py_INCREF(a); + } else { + source->ref(); + a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, + true, true, source->get_type_index()); + } + const TransformState *result = _this->_invert_composition_cache.get_data(si)._result; + if (result == (TransformState *)NULL) { + b = Py_None; + Py_INCREF(b); + } else { + result->ref(); + b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, + true, true, result->get_type_index()); + } + + PyTuple_SET_ITEM(tuple, 0, a); + PyTuple_SET_ITEM(tuple, 1, b); + + nassertr(i < num_states, list); + PyList_SET_ITEM(list, i, tuple); + ++i; + } + nassertr(i == num_states, list); + return list; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_states +// Access: Published, Static +// Description: Returns a list of all of the TransformState objects +// in the state cache. The order of elements in this +// cache is arbitrary. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_states() { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; + if (TransformState::_states == (TransformState::States *)NULL) { + return PyList_New(0); + } + LightReMutexHolder holder(*TransformState::_states_lock); + + size_t num_states = TransformState::_states->get_num_entries(); + PyObject *list = PyList_New(num_states); + size_t i = 0; + + int size = TransformState::_states->get_size(); + for (int si = 0; si < size; ++si) { + if (!TransformState::_states->has_element(si)) { + continue; + } + const TransformState *state = TransformState::_states->get_key(si); + state->ref(); + PyObject *a = + DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState, + 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; +} + +//////////////////////////////////////////////////////////////////// +// Function: Extension::get_unused_states +// Access: Published, Static +// Description: Returns a list of all of the "unused" TransformState +// objects in the state cache. See +// get_num_unused_states(). +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +get_unused_states() { + IMPORT_THIS struct Dtool_PyTypedObject Dtool_TransformState; + if (TransformState::_states == (TransformState::States *)NULL) { + return PyList_New(0); + } + LightReMutexHolder holder(*TransformState::_states_lock); + + PyObject *list = PyList_New(0); + int size = TransformState::_states->get_size(); + for (int si = 0; si < size; ++si) { + if (!TransformState::_states->has_element(si)) { + continue; + } + const TransformState *state = TransformState::_states->get_key(si); + if (state->get_cache_ref_count() == state->get_ref_count()) { + state->ref(); + PyObject *a = + DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState, + true, true, state->get_type_index()); + PyList_Append(list, a); + Py_DECREF(a); + } + } + return list; +} + +#endif // HAVE_PYTHON diff --git a/panda/src/pgraph/transformState_ext.h b/panda/src/pgraph/transformState_ext.h new file mode 100644 index 0000000000..81f3312eb6 --- /dev/null +++ b/panda/src/pgraph/transformState_ext.h @@ -0,0 +1,43 @@ +// Filename: transformState_ext.h +// Created by: CFSworks (31Mar14) +// +//////////////////////////////////////////////////////////////////// +// +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef TRANSFORMSTATE_EXT_H +#define TRANSFORMSTATE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "transformState.h" +#include "py_panda.h" + +//////////////////////////////////////////////////////////////////// +// Class : Extension +// Description : This class defines the extension methods for +// TransformState, which are called instead of +// any C++ methods with the same prototype. +//////////////////////////////////////////////////////////////////// +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_composition_cache() const; + PyObject *get_invert_composition_cache() const; + static PyObject *get_states(); + static PyObject *get_unused_states(); +}; + +#endif // HAVE_PYTHON + +#endif // TRANSFORMSTATE_EXT_H From 6ddab655114c2063614e35737e86378235ab4bcc Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 4 Apr 2014 23:24:46 +0000 Subject: [PATCH 21/26] Fix SubprocessWindow compile error --- panda/src/display/subprocessWindow.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/display/subprocessWindow.cxx b/panda/src/display/subprocessWindow.cxx index 07daf5090e..ebac3ca3c0 100644 --- a/panda/src/display/subprocessWindow.cxx +++ b/panda/src/display/subprocessWindow.cxx @@ -191,7 +191,7 @@ begin_flip() { _buffer->get_fb_properties()); bool copied = - _gsg->framebuffer_copy_to_ram(_texture, -1, + _gsg->framebuffer_copy_to_ram(_texture, 0, -1, _overlay_display_region, buffer); if (copied) { From 4b1c4ff3c890c236fcaa2ff3d3abf8dc3b2ee653 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 5 Apr 2014 08:55:50 +0000 Subject: [PATCH 22/26] Fix use of deprecated NodePath.id() --- direct/src/directtools/DirectSelection.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index 6d1ec0e83f..852cbd2cab 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -83,7 +83,7 @@ class SelectedNodePaths(DirectObject): break # Get this pointer - id = nodePath.id() + id = nodePath.get_key() # First see if its already in the selected dictionary dnp = self.getSelectedDict(id) # If so, deselect it @@ -104,7 +104,7 @@ class SelectedNodePaths(DirectObject): # Show its bounding box dnp.highlight(fRecompute = 0) # Add it to the selected dictionary - self.selectedDict[dnp.id()] = dnp + self.selectedDict[dnp.get_key()] = dnp self.selectedList.append(dnp) # [gjeon] # And update last @@ -117,7 +117,7 @@ class SelectedNodePaths(DirectObject): def deselect(self, nodePath): """ Deselect the specified node path """ # Get this pointer - id = nodePath.id() + id = nodePath.get_key() # See if it is in the selected dictionary dnp = self.getSelectedDict(id) if dnp: @@ -240,7 +240,7 @@ class SelectedNodePaths(DirectObject): def getDirectNodePath(self, nodePath): # Get this pointer - id = nodePath.id() + id = nodePath.get_key() # First check selected dict dnp = self.getSelectedDict(id) if dnp: From 5abc6aa2fce229d5b7303cc0435e061a6af21345 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 5 Apr 2014 21:47:54 +0000 Subject: [PATCH 23/26] Oops, fix compile error --- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index fd48033eec..de3df8e994 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -1902,7 +1902,6 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, // must use a render target type texture for StretchRect tex->set_render_to_texture(true); - int view = dr->get_target_tex_view(); TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { return false; From 51dffd0f5a2dfb9fe72e711e91ed1f02cd454a54 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 16 Apr 2014 13:09:12 +0000 Subject: [PATCH 24/26] Commit patch by cfsworks to clean up use of exec() and eval() --- direct/src/distributed/MsgTypes.py | 4 +--- direct/src/distributed/MsgTypesCMU.py | 4 +--- direct/src/gui/OnscreenGeom.py | 5 ++--- direct/src/gui/OnscreenImage.py | 5 ++--- direct/src/gui/OnscreenText.py | 5 ++--- direct/src/leveleditor/ObjectMgrBase.py | 12 ++++++------ direct/src/particles/Particles.py | 4 ++-- direct/src/showbase/ElementTree.py | 5 +---- direct/src/showbase/PythonUtil.py | 2 +- 9 files changed, 18 insertions(+), 28 deletions(-) diff --git a/direct/src/distributed/MsgTypes.py b/direct/src/distributed/MsgTypes.py index 283701e3b4..231cf78733 100644 --- a/direct/src/distributed/MsgTypes.py +++ b/direct/src/distributed/MsgTypes.py @@ -107,9 +107,7 @@ MsgName2Id = { MsgId2Names = invertDictLossless(MsgName2Id) # put msg names in module scope, assigned to msg value -for name, value in MsgName2Id.items(): - exec('%s = %s' % (name, value)) -del name, value +globals().update(MsgName2Id) # These messages are ignored when the client is headed to the quiet zone QUIET_ZONE_IGNORED_LIST = [ diff --git a/direct/src/distributed/MsgTypesCMU.py b/direct/src/distributed/MsgTypesCMU.py index 8501866a5b..b91a505453 100644 --- a/direct/src/distributed/MsgTypesCMU.py +++ b/direct/src/distributed/MsgTypesCMU.py @@ -26,6 +26,4 @@ MsgName2Id = { MsgId2Names = invertDictLossless(MsgName2Id) # put msg names in module scope, assigned to msg value -for name, value in MsgName2Id.items(): - exec('%s = %s' % (name, value)) -del name, value +globals().update(MsgName2Id) diff --git a/direct/src/gui/OnscreenGeom.py b/direct/src/gui/OnscreenGeom.py index fdd0f90f72..d9ef571aa6 100644 --- a/direct/src/gui/OnscreenGeom.py +++ b/direct/src/gui/OnscreenGeom.py @@ -113,8 +113,7 @@ class OnscreenGeom(DirectObject, NodePath): for option, value in kw.items(): # Use option string to access setter function try: - setter = eval('self.set' + - string.upper(option[0]) + option[1:]) + setter = getattr(self, 'set' + option[0].upper() + option[1:]) if (((setter == self.setPos) or (setter == self.setHpr) or (setter == self.setScale)) and @@ -133,7 +132,7 @@ class OnscreenGeom(DirectObject, NodePath): def cget(self, option): # Get current configuration setting. # This is for compatibility with DirectGui functions - getter = eval('self.get' + string.upper(option[0]) + option[1:]) + getter = getattr(self, 'get' + option[0].upper() + option[1:]) return getter() # Allow index style refererences diff --git a/direct/src/gui/OnscreenImage.py b/direct/src/gui/OnscreenImage.py index 21486d2fb3..50923eec19 100644 --- a/direct/src/gui/OnscreenImage.py +++ b/direct/src/gui/OnscreenImage.py @@ -130,8 +130,7 @@ class OnscreenImage(DirectObject, NodePath): for option, value in kw.items(): # Use option string to access setter function try: - setter = eval('self.set' + - string.upper(option[0]) + option[1:]) + setter = getattr(self, 'set' + option[0].upper() + option[1:]) if (((setter == self.setPos) or (setter == self.setHpr) or (setter == self.setScale)) and @@ -150,7 +149,7 @@ class OnscreenImage(DirectObject, NodePath): def cget(self, option): # Get current configuration setting. # This is for compatibility with DirectGui functions - getter = eval('self.get' + string.upper(option[0]) + option[1:]) + getter = getattr(self, 'get' + option[0].upper() + option[1:]) return getter() # Allow index style refererences diff --git a/direct/src/gui/OnscreenText.py b/direct/src/gui/OnscreenText.py index f8160065db..ed212d2643 100644 --- a/direct/src/gui/OnscreenText.py +++ b/direct/src/gui/OnscreenText.py @@ -381,8 +381,7 @@ class OnscreenText(DirectObject, NodePath): for option, value in kw.items(): # Use option string to access setter function try: - setter = eval('self.set' + - string.upper(option[0]) + option[1:]) + setter = getattr(self, 'set' + option[0].upper() + option[1:]) if setter == self.setPos: setter(value[0], value[1]) else: @@ -397,7 +396,7 @@ class OnscreenText(DirectObject, NodePath): def cget(self, option): # Get current configuration setting. # This is for compatibility with DirectGui functions - getter = eval('self.get' + string.upper(option[0]) + option[1:]) + getter = getattr(self, 'get' + option[0].upper() + option[1:]) return getter() def setAlign(self, align): diff --git a/direct/src/leveleditor/ObjectMgrBase.py b/direct/src/leveleditor/ObjectMgrBase.py index 7838d3922b..2524ca404e 100755 --- a/direct/src/leveleditor/ObjectMgrBase.py +++ b/direct/src/leveleditor/ObjectMgrBase.py @@ -189,9 +189,9 @@ class ObjectMgrBase: if funcName.startswith('.'): # when it's using default objectHandler if self.editor: - func = Functor(eval("self.editor.objectHandler%s"%funcName)) + func = Functor(getattr(self.editor, "objectHandler%s"%funcName)) else: # when loaded outside of LE - func = Functor(eval("base.objectHandler%s"%funcName)) + func = Functor(getattr(base, "objectHandler%s"%funcName)) else: # when it's not using default objectHandler, whole name of the handling obj # should be included in function name @@ -686,11 +686,11 @@ class ObjectMgrBase: if type(funcName) == types.StringType: if funcName.startswith('.'): if self.editor: - func = Functor(eval("self.editor.objectHandler%s"%funcName), **kwargs) - undoFunc = Functor(eval("self.editor.objectHandler%s"%funcName), **undoKwargs) + func = Functor(getattr(self.editor, "objectHandler%s"%funcName), **kwargs) + undoFunc = Functor(getattr(self.editor, "objectHandler%s"%funcName), **undoKwargs) else: # when loaded outside of LE - func = Functor(eval("base.objectHandler%s"%funcName), **kwargs) - undoFunc = Functor(eval("base.objectHandler%s"%funcName), **undoKwargs) + func = Functor(getattr(base, "objectHandler%s"%funcName), **kwargs) + undoFunc = Functor(getattr(base, ".objectHandler%s"%funcName), **undoKwargs) else: func = Functor(eval(funcName), **kwargs) undoFunc = Functor(eval(funcName), **undoKwargs) diff --git a/direct/src/particles/Particles.py b/direct/src/particles/Particles.py index 974ff4af9e..cdf0550d05 100644 --- a/direct/src/particles/Particles.py +++ b/direct/src/particles/Particles.py @@ -354,7 +354,7 @@ class Particles(ParticleSystem): else: file.write(targ+'.renderer.setColorBlendMode(ColorBlendAttrib.%s)\n' % cbmLut[cbMode]) cim = self.renderer.getColorInterpolationManager() - segIdList = eval('['+cim.getSegmentIdList().replace(' ',', ')+']') + segIdList = [int(seg) for seg in cim.getSegmentIdList().split()] for sid in segIdList: seg = cim.getSegment(sid) if seg.isEnabled(): @@ -457,7 +457,7 @@ class Particles(ParticleSystem): else: file.write(targ+'.renderer.setColorBlendMode(ColorBlendAttrib.%s)\n' % cbmLut[cbMode]) cim = self.renderer.getColorInterpolationManager() - segIdList = eval('['+cim.getSegmentIdList().replace(' ',', ')+']') + segIdList = [int(seg) for seg in cim.getSegmentIdList().split()] for sid in segIdList: seg = cim.getSegment(sid) if seg.isEnabled(): diff --git a/direct/src/showbase/ElementTree.py b/direct/src/showbase/ElementTree.py index 3f368edd39..4e52ff2396 100755 --- a/direct/src/showbase/ElementTree.py +++ b/direct/src/showbase/ElementTree.py @@ -749,10 +749,7 @@ def _encode(s, encoding): except AttributeError: return s # 1.5.2: assume the string uses the right encoding -if sys.version[:3] == "1.5": - _escape = re.compile(r"[&<>\"\x80-\xff]+") # 1.5.2 -else: - _escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"')) +_escape = re.compile(u"[&<>\"\u0080-\uffff]+") _escape_map = { "&": "&", diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index 9f18522c2e..1bcade4031 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -4188,7 +4188,7 @@ def unescapeHtmlString(s): char = ' ' elif char == '%': if i < (len(s)-2): - num = eval('0x' + s[i+1:i+3]) + num = int(s[i+1:i+3], 16) char = chr(num) i += 2 i += 1 From caad44773b473f3002f682a1236006171ed7f3ce Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 16 Apr 2014 13:49:53 +0000 Subject: [PATCH 25/26] Commit patch by cfsworks to fix double-free issue with ffmpeg --- panda/src/ffmpeg/ffmpegVirtualFile.cxx | 23 +++++++++++++---------- panda/src/ffmpeg/ffmpegVirtualFile.h | 1 - 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegVirtualFile.cxx b/panda/src/ffmpeg/ffmpegVirtualFile.cxx index 098a5ef471..8b459384a2 100644 --- a/panda/src/ffmpeg/ffmpegVirtualFile.cxx +++ b/panda/src/ffmpeg/ffmpegVirtualFile.cxx @@ -38,7 +38,6 @@ FfmpegVirtualFile() : _format_context(NULL), _in(NULL), _owns_in(false), - _buffer(NULL), _buffer_size(ffmpeg_read_buffer_size) { } @@ -106,8 +105,11 @@ open_vfs(const Filename &filename) { _start = 0; _size = vfile->get_file_size(_in); - _buffer = (unsigned char*) av_malloc(_buffer_size); - _io_context = avio_alloc_context(_buffer, _buffer_size, 0, (void*) this, + // NOTE: The AVIO system owns the buffer after allocation and may realloc it + // internally. Therefore, when we're done with the buffer, we use + // _io_context->buffer to deallocate it rather than holding on to this pointer. + unsigned char *buffer = (unsigned char*) av_malloc(_buffer_size); + _io_context = avio_alloc_context(buffer, _buffer_size, 0, (void*) this, &read_packet, 0, &seek); _format_context = avformat_alloc_context(); @@ -157,8 +159,11 @@ open_subfile(const SubfileInfo &info) { _in->seekg(_start); - _buffer = (unsigned char*) av_malloc(_buffer_size); - _io_context = avio_alloc_context(_buffer, _buffer_size, 0, (void*) this, + // NOTE: The AVIO system owns the buffer after allocation and may realloc it + // internally. Therefore, when we're done with the buffer, we use + // _io_context->buffer to deallocate it rather than holding on to this pointer. + unsigned char *buffer = (unsigned char*) av_malloc(_buffer_size); + _io_context = avio_alloc_context(buffer, _buffer_size, 0, (void*) this, &read_packet, 0, &seek); _format_context = avformat_alloc_context(); @@ -197,15 +202,13 @@ close() { } if (_io_context != NULL) { + if (_io_context->buffer != NULL) { + av_free(_io_context->buffer); + } av_free(_io_context); _io_context = NULL; } - if (_buffer != NULL) { - av_free(_buffer); - _buffer = NULL; - } - if (_owns_in) { nassertv(_in != NULL); VirtualFileSystem::close_read_file(_in); diff --git a/panda/src/ffmpeg/ffmpegVirtualFile.h b/panda/src/ffmpeg/ffmpegVirtualFile.h index a692a31625..083e28174f 100644 --- a/panda/src/ffmpeg/ffmpegVirtualFile.h +++ b/panda/src/ffmpeg/ffmpegVirtualFile.h @@ -67,7 +67,6 @@ private: istream *_in; pifstream _file_in; bool _owns_in; - unsigned char *_buffer; int _buffer_size; }; From 78ed00ef2b4354e50793a7f619c43a97885f8353 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 18 Apr 2014 15:22:56 +0000 Subject: [PATCH 26/26] fix uninitialised _frame pointer (thanks cfsworks for pointing it out) --- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index 603edfa4d5..7269209763 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -56,7 +56,8 @@ FfmpegAudioCursor(FfmpegAudio *src) : _resample_ctx(0), #endif _buffer(0), - _buffer_alloc(0) + _buffer_alloc(0), + _frame(0) { if (!_ffvfile.open_vfs(_filename)) { cleanup();