Merge branch 'master' into astron-master

This commit is contained in:
Sam Edwards 2014-05-06 08:10:24 -06:00
commit 227dbfb34d
104 changed files with 2080 additions and 1012 deletions

View File

@ -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:

View File

@ -139,9 +139,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 = [

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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)

View File

@ -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():

View File

@ -22,6 +22,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#endif // _WIN32
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__)

View File

@ -24,10 +24,9 @@
#include <sys/stat.h> // for mkdir()
#include <errno.h>
#include <string.h> // strerror()
#include <unistd.h>
#endif
////////////////////////////////////////////////////////////////////
// Function: get_dirname
// Description: Returns the directory component of the indicated

View File

@ -28,6 +28,7 @@
#include <sys/select.h>
#include <signal.h>
#include <dlfcn.h>
#include <unistd.h>
#endif
////////////////////////////////////////////////////////////////////

View File

@ -22,6 +22,10 @@
#include <algorithm>
#ifndef _WIN32
#include <unistd.h>
#endif
////////////////////////////////////////////////////////////////////
// Function: P3DHost::Constructor
// Access: Private

View File

@ -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 = {
"&": "&amp;",

View File

@ -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

View File

@ -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;
}

View File

@ -76,6 +76,7 @@ private:
WT_inquiry,
WT_getbuffer,
WT_releasebuffer,
WT_iter_next,
};
class SlottedFunctionDef {

View File

@ -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)

View File

@ -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.
@ -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:
@ -4721,7 +4719,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,

View File

@ -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=""):

View File

@ -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;

View File

@ -39,7 +39,7 @@
#import <AppKit/NSImage.h>
#import <AppKit/NSScreen.h>
#import <OpenGL/OpenGL.h>
//#import <Carbon/Carbon.h>
#import <Carbon/Carbon.h>
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();
}

View File

@ -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 "

View File

@ -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;

View File

@ -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

View File

@ -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 &copy) :
_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)
{
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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();

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);
}
////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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) {

View File

@ -202,8 +202,8 @@ help() {
" -C <extract_dir>\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 &params) {
filenames.push_back(subfile_name);
}
// Change current working directory, if requested.
if (got_chdir_to && !chdir_to.chdir()) {
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();

View File

@ -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);

View File

@ -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();

View File

@ -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()

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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();
@ -1902,7 +1902,6 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
// 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;
@ -1918,7 +1917,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 +2019,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 +2037,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 +2052,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 +2212,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 +2445,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));

View File

@ -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();

View File

@ -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()

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 \

View File

@ -16,7 +16,9 @@
#ifdef HAVE_PYTHON
#ifndef CPPPARSER
IMPORT_THIS struct Dtool_PyTypedObject Dtool_EggNode;
#endif
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::get_children

View File

@ -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();

View File

@ -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);

View File

@ -67,7 +67,6 @@ private:
istream *_in;
pifstream _file_in;
bool _owns_in;
unsigned char *_buffer;
int _buffer_size;
};

View File

@ -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;

View File

@ -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:

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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<NodePath>::
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<NodePath>::
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<NodePath>::
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);
}
////////////////////////////////////////////////////////////////////

View File

@ -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__());
}
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,5 @@
#include "nodePath_ext.cxx"
#include "nodePathCollection_ext.cxx"
#include "pandaNode_ext.cxx"
#include "renderState_ext.cxx"
#include "transformState_ext.cxx"

View File

@ -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<PythonTagData::iterator, bool> 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

View File

@ -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<PandaNode>;
};
////////////////////////////////////////////////////////////////////

View File

@ -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<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) Extension<PandaNode>::
__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<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 *Extension<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 = _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<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 Extension<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);
PandaNode::CDWriter cdata(_this->_cycler);
Py_XINCREF(value);
pair<PandaNode::PythonTagData::iterator, bool> 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<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 *Extension<PandaNode>::
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<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 Extension<PandaNode>::
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<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 Extension<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);
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<PandaNode>::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<PandaNode>::
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<PandaNode>::get_tag_keys
// Access: Published
// Description: This variant on get_tag_keys returns
// a Python list of strings.
////////////////////////////////////////////////////////////////////
PyObject *Extension<PandaNode>::
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<PandaNode>::get_python_tag_keys
// Access: Published
// Description: This variant on get_python_tag_keys returns
// a Python list of strings.
////////////////////////////////////////////////////////////////////
PyObject *Extension<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

View File

@ -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<PandaNode>
// Description : This class defines the extension methods for
// PandaNode, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<PandaNode> : public ExtensionBase<PandaNode> {
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

View File

@ -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

View File

@ -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<RenderState>;
};
INLINE ostream &operator << (ostream &out, const RenderState &state) {

View File

@ -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<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 *Extension<RenderState>::
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<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 *Extension<RenderState>::
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<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 *Extension<RenderState>::
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

View File

@ -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<RenderState>
// Description : This class defines the extension methods for
// RenderState, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<RenderState> : public ExtensionBase<RenderState> {
public:
PyObject *get_composition_cache() const;
PyObject *get_invert_composition_cache() const;
static PyObject *get_states();
};
#endif // HAVE_PYTHON
#endif // RENDERSTATE_EXT_H

View File

@ -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

View File

@ -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<TransformState>;
};
INLINE ostream &operator << (ostream &out, const TransformState &state) {

View File

@ -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<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 *Extension<TransformState>::
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<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 *Extension<TransformState>::
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<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 *Extension<TransformState>::
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<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 *Extension<TransformState>::
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

View File

@ -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<TransformState>
// Description : This class defines the extension methods for
// TransformState, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<TransformState> : public ExtensionBase<TransformState> {
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

View File

@ -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

View File

@ -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 &copy) :
_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 &copy) {
_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

View File

@ -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);

View File

@ -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 \

View File

@ -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

View File

@ -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 &copy);

141
panda/src/putil/buttonMap.I Normal file
View File

@ -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_label
// Access: Published
// 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_label(int i) const {
return _buttons[i]->_label;
}
////////////////////////////////////////////////////////////////////
// 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<int, ButtonNode>::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_label
// 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_label(ButtonHandle raw) const {
pmap<int, ButtonNode>::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._label;
}
}
////////////////////////////////////////////////////////////////////
// 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
// 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_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_label(raw_button);
}
}

View File

@ -0,0 +1,67 @@
// 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 &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;
bnode._label = 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<ButtonNode*>::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";
}
}

View File

@ -0,0 +1,81 @@
// 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 EXPCL_PANDA_PUTIL 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_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_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 = "");
private:
struct ButtonNode {
ButtonHandle _raw;
ButtonHandle _mapped;
string _label;
};
pmap<int, ButtonNode> _button_map;
pvector<ButtonNode*> _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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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"

View File

@ -15,6 +15,8 @@
#include "rocketRegion_ext.h"
#include "extension.h"
#ifdef HAVE_PYTHON
#ifndef CPPPARSER
#define HAVE_LONG_LONG 1
#include <Rocket/Core/Context.h>
@ -48,3 +50,5 @@ get_context() const {
}
return NULL;
}
#endif

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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();

Some files were not shown because too many files have changed in this diff Show More